覆盖上的has_many ActiveRecord的<<操作:通过关系,以接受连接模型数

2019-08-01 09:00发布

我有三类:个人,位置,和目录。

  • 一个人的has_many:目录,:通过=>:位置。
  • 一个目录的has_many:人:通过=>:位置。
  • 两个人与目录的has_many:位置。
  • 该位置模型中,除了具有一个ID,一个为person_id和directory_id,具有一个或多个附加字段(例如,标题)。

我希望能够做的就是将数据添加到加盟模式,比如标题场,每次我一个人添加到Directory.people收集时间。 通常<<操作将不会削减它。 ID EST:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << person

这将一个人添加到一个目录对象的人收藏,但不会让我的数据分配给连接模型的机会。 所以,在这个网站做了很多的研究,我发现了另一种方式的个人数据添加到人收藏并添加链接人事和目录,ID EST的位置:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
position = person.positions.build(:directory_id => directory.id, :title => "Administrative Assistant") 
position.save

这是麻烦的。 同样麻烦的方式是:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
position = Position.new(directory_id: directory.id, person_id: person.id, title: "Administrative Assistant")

再次,似乎是错误的,因为我希望能够强调人与目录之间的关系,我相信这是使用的has_many什么使:通过适当的。

我希望能够做的是使用<<操作,只是通过其它数据,例如:

directory = Directory.last # Let's assume that retrieves a Directory object
person = Person.last # Let's assume that retrieves a Person object
directory.people << person, :position => {:title => "Administrative Assistant"}

我已经重载<<在我的has_many操作:通过声明,如下所示:

has_many :people, :through => :positions do
  def << *args
    arg = args.first
    if arg.is_a?(Person)
      self.push([arg]) 
    elsif arg.is_a?(Hash)
      # Don't know what to do in here (see below)
    else
      raise "Invalid Value" # There's a better error to raise here, but good enough for now.
    end
  end
end

得到这个工作的好处是,它运作良好语法,并让我简明而添加的人到Directory对象的人收藏数据分配给参加对象(的位置)。

但我不能让它工作,因为我需要能够访问的目录对象,其中在<<运算符的左侧的人收藏是一个属性,以建立一个位置,并将其保存到数据库中。

所以,我的问题是:

  1. 有没有从一个对象的属性来访问对象的方法吗?
  2. 在备选方案中,有另一种方式重载<<操作,这样我可以很容易地将数据分配到加盟模式,同时加入一个对象的集合?

非常感谢您的帮助和深思熟虑的回应。 我已经远离黑客在这半天不得要领。

感谢PinnyM,谁回答了这个问题,我能想出这个实现:

module AddToPeopleAndPositionExtension
  def << *args
    arg = args.first
      if arg.is_a?(Person)
        self.push([arg]) 
        return self
      elsif arg.is_a?(Hash)
        directory = proxy_association.owner
        person = arg[:person]
        position = person.positions.build(:directory_id => directory.id, :title => arg[:position][:title]) 
        position.save
      else
        raise "Invalid Value"
      end
  end
end

class Directory < ActiveRecord::Base  
  # Relationships
  has_many :positions
  has_many :people, :through => :positions, :extend => AddToPeopleAndPositionExtension
end

这让我叫<<运营商在标准的方式,如果我没在意就加入模型,如发生了什么:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << person

而且,我还可以把它在指定的连接模式一样的属性的方法:

directory = Directory.last     # Let's assume that retrieves a Directory object
person = Person.last           # Let's assume that retrieves a Person object
directory.people << {:person => person, :position => {:title => "Administrative Assistant"}}

Answer 1:

您可以使用proxy_association帮手块内获得关联和proxy_association.owner得到Directory对象本身。 见这里的一些这方面的更多信息。



文章来源: Override ActiveRecord << operator on has_many :through relationship, to accept data for the join model