我有一组这样的类:
class Owner
has_one :animal
end
class Animal < AR::Base
TYPES = ['Lion','Cat']
# has a type field
belongs_to :owner
end
class Lion < Animal
def speak
'roar'
end
end
class Cat < Animal
def speak
'meow'
end
end
所以我与所有者和动物有关联,每只动物都有一种类型。这一切都有效,直到我这样打电话:
owner.animal.speak
返回类型为&#39; Animal&#39;然后尝试调用该方法&#39;说&#39;这是父母未定义的。如何让Rails返回适当的子类而不是父类?
答案 0 :(得分:0)
ActiveRecord和Arel不容易像这样处理子类。你最好的选择是让Animal类在内部跟踪它自己的类型。所以:
class Animal < AR::Base
TYPES = ['Lion','Cat']
belongs_to :owner
def speak
case self.type
when "Lion"
"roar"
when "Cat"
"meow"
end
end
end
答案 1 :(得分:0)
我刚刚启动了一个新的Rails项目并使用了您的示例,它按预期工作。在type
列中,您确定类型为"Cat"
还是"Lion"
,而不是小写或下标版本?
我建议将has_one :cat
和has_one :lion
添加到Owner
。然后,要实例化它们,您可以调用Rails'owner.build_cat
,这是构建新实例的has_one
方式。 (在has_many
owner.cats.build
。{/ p>
这样,您确定type
已正确完成。
这就是我得到的。
> owner.animal
=> nil
> owner.cat
=> nil
> owner.build_cat
=> #<Cat id: nil, owner_id: 1, type: "Cat" ...
> owner.cat.save
=> true
> owner.cat
=> #<Cat id: 1, owner_id: 1, type: "Cat" ...
> owner.animal
=> nil # Whaaaa?
(所有者实例有一个关联缓存,因为我们已经调用了动物,它是零,它已被缓存为零)
> owner.clear_association_cache
=> {}
> owner.animal
=> #<Cat id: 1, owner_id: 1, type: "Cat" ...
> owner.animal.speak
=> 'meow'
> owner.animal.class
=> Cat
> owner.animal.class.to_s == owner.animal.type
=> true
希望有所帮助!