强制使用多态类型来获取属性

时间:2012-11-02 17:42:21

标签: ruby-on-rails polymorphic-associations

我有一个标准的多态关系设置如:

#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?进行测试。

1 个答案:

答案 0 :(得分:1)

您可以通过创建FooQux扩展的基类来提供默认值。而不是

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,您可以使用Quxname中包含的mixin来抛出异常。的 Read an example of this sort of implementation here

注意如果这些模型在表格中有关联的name列的可能性,您可能希望在重载的{{1}中的某处包含read_attribute(:name) }} 方法。的 See the docs on read_attribute