我有一个标准的多态关系设置如:
#Foo
has_many: bar, as: foobar
#Qux
has_many: bar, as: foobar
#Bar
belongs_to :foobar, polymorphic: true
我希望能够强制has_many: bar, as: foobar
具有某些属性的模型,例如name
,所以我可以执行以下操作:
bar.foobar.name
并且知道当时哪种型号foobar无关紧要。 (因为所有foobars都有name属性)
有没有办法做到这一点,或者我每次想要使用它时都必须使用responds_to?
进行测试。
答案 0 :(得分:1)
您可以通过创建Foo
和Qux
扩展的基类来提供默认值。而不是
class Foo < ActiveRecord::Base
has_many: bar, as: foobar
end
class Qux < ActiveRecord::Base
has_many: bar, as: foobar
end
你可以做点什么
class Foobar < ActiveRecord::Base
has_many: bar, as: foobar
end
class Foo < Foobar; end
class Qux < Foobar; end
然后,您可以为要扩展Foobar
的类的属性创建默认的访问器方法。
class Foobar < ActiveRecord::Base
has_many: bar, as: foobar
def name
"some default name"
end
end
class Foo < Foobar
def name
"some overloaded name for Foo"
end
end
class Qux < Foobar; end
您可以按name
中所示重载Foo
,或按Qux
中所示省略它。无论如何,name
属性都可用,即使它只是Foobar
的默认属性。
foo = Foo.new
puts foo.name # "some overloaded name for Foo"
qux = Qux.new
puts qux.name # "some default name"
如果您希望通过其他语言中常见的接口或抽象类创建更多合同,Ruby也不支持。但是,如果未定义Foo
,您可以使用Qux
和name
中包含的mixin来抛出异常。的 Read an example of this sort of implementation here 强>
注意如果这些模型在表格中有关联的name
列的可能性,您可能希望在重载的{{1}中的某处包含read_attribute(:name)
}} 方法。的 See the docs on read_attribute
强>