我的导轨应用程序中有一个父类个人和子类学生和教授。
使用名为“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
答案 0 :(得分:0)
我没有使用过这个宝石,但为了给你一些帮助,here's what I've found和this:
他们都提到你通过你的关系调用一个对象,这会对多态或类似的东西产生混淆。这两个帖子无法解决问题,我认为这是因为他们可以为他们的关系找到正确的对象
进一步观察,我发现了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.individual
或some_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