将孩子传递给父类型的容器

时间:2014-04-30 09:03:40

标签: ruby-on-rails

我的导轨应用程序中有一个父类个人和子类学生教授

使用名为“acts_as_relation”的gem处理继承,该gem模拟多个表继承。

此外,我还有一个动作,在该动作中,学生实例被附加到个人列表中。通常情况下我会期望这一点没有任何问题,但我得到了这个错误:

ActiveRecord::AssociationTypeMismatch: Individual(#70220161296060) expected, got Student(#70220161349360)

以下是我的模特:

class Individual < ActiveRecord::Base
    acts_as_superclass
end

class Student < ActiveRecord::Base
      acts_as :individual
end

class Professor < ActiveRecord::Base
      acts_as :individual
end

2 个答案:

答案 0 :(得分:0)

我没有使用过这个宝石,但为了给你一些帮助,here's what I've foundthis

  

他们都提到你通过你的关系调用一个对象,这会对多态或类似的东西产生混淆。这两个帖子无法解决问题,我认为这是因为他们可以为他们的关系找到正确的对象


进一步观察,我发现了this tutorial on the gem homepage

  

acts_as_relation使用多态has_one关联来模拟   多表继承。对于电子商务示例,您会   将产品声明为超级模型,并将其作为acts_as的所有类型   :产品(如果您愿意,可以使用别名is_a和   is_a_superclass)

class Product < ActiveRecord::Base
  acts_as_superclass
end

class Pen < ActiveRecord::Base
  acts_as :product
end

class Book < ActiveRecord::Base
  acts_as :product
end
  

要使其工作,您需要声明外键列和a   声明超类的模型中的type列。要做到这一点,你可以   在产品create_table上设置:as_relation_superclass选项为true   (或传递协会名称):

create_table :products, :as_relation_superclass => true do |t|
  # ...
end
  

或者像对多态的belongs_to关联一样声明它们,它   在这种情况下,您必须将名称传递给acts_as:作为选项:

change_table :products do |t|
  t.integer :producible_id
  t.string  :producible_type
end

class Pen < ActiveRecord::Base
  acts_as :product, :as => :producible
end

class Book < ActiveRecord::Base
  acts_as :product, :as => :producible
end

您确定您的数据表设置正确吗?

答案 1 :(得分:0)

我在项目中解决此问题的方法是使用instance_ofsome_class.individuals << student_instance.individual

这里的事情不是真正的MTI,所以你的个人集合只接受个人实例。如果您致电some_student_instance.individualsome_professor_instance.individual,您将获得与您的特定实例相关的单个实例。 然后使用该集合,如果您需要学生或教授,您需要做的就是致电individual_in_collection.specific。例如:

p = Professor.create
a_model.individuals << p.individual
puts "#{a_model.individuals.first.class.name}"
=> Individual
puts "#{a_model.individuals.first.specific.class.name}"
=> Professor