Ruby on rails关联父母

时间:2015-09-24 15:31:41

标签: ruby-on-rails ruby activerecord

我想知道,无论关联是什么(简单的belongs_to,多态......),当我建立一个关联时:

class Toto < ActiveRecord::Base
 belongs_to :test_one
 belongs_to :test_two
end

class TestOne < ActiveRecord::Base
 has_many :totos
end

class TestTwo < ActiveRecord::Base
 has_many :totos
end

然后

test_one = TestOne.create
test_two = TestTwo.create

test1 = test_one.totos.create
test2 = test_two.totos.create

我想知道Toto的回调是什么对象实例化我。在这种情况下,它显然是test_one然后是test_two。我知道我可以检查一下id,但问题出在我做的时候:

test3 = test_one.totos.create(test_two: test_two)

我无法知道test3是通过test_one还是test_two创建的。

谢谢。

2 个答案:

答案 0 :(得分:2)

根据您的示例,我了解您要识别与totos对象关联的对象类型(has_many:totos)。

由于有多个不同的对象可能通过has_many和belongs_to关联与totos对象相关联,因此您可能希望首先执行某种验证以识别关联对象的类型。

第一个答案:

只有事先知道has_many:totos

的所有对象类型,这才有效
if test3.respond_to?(:test_one)
  test = test3.test_one
elsif test3.respond_to?(:test_two)
  test = test3.test_two
end

第二个答案:

我在Stackoverflow上找到了this,它以某种方式回答了你的问题。所以,如果我改写答案:

def get_belongs_to(object)
  associated = []
  object.class.reflect_on_all_associations(:belongs_to).map do |reflection|
    associated << object.try(reflection.name)
  end
  associated.compact
end

此方法将返回与totos对象关联的所有对象的数组。当totos同时属于多个对象时,例如test_one和test_two,这也适用。以下是:

associated_objects = get_belongs_to(test3)

并且在您的情况下associated_objects[0]将产生您想要的对象。

希望这有帮助。

答案 1 :(得分:0)

Rails不会保留您正在查找的数据,因此如果您需要,您必须自己存储它。这意味着您需要迁移新字段:

rails generate migration AddOriginalParentTypeToTotos original_parent_type:string
rake db:migrate

然后,您可以覆盖分配方法,以便分配的第一个父级将分配original_parent_type属性(分配后它将保持不变):

class Toto < ActiveRecord::Base
  def test_one=(val)
    self[:original_parent_type] ||= 'test_one'
    super
  end
  def test_one_id=(val)
    self[:original_parent_type] ||= 'test_one'
    super
  end
  def test_two=(val)
    self[:original_parent_type] ||= 'test_two'
    super
  end
  def test_two_id=(val)
    self[:original_parent_type] ||= 'test_two'
    super
  end
end

然后,您可以使用send添加original_parent方法:

class Toto < ActiveRecord::Base
  def original_parent
    send(original_parent_type) if original_parent_type
  end
end