I have a standard polymorphic relation set up like:
#Foo
has_many: bar, as: foobar
#Qux
has_many: bar, as: foobar
#Bar
belongs_to :foobar, polymorphic: true
I want to be able to enforce a model that has_many: bar, as: foobar to have certain attributes for example a name, so I can do something like:
bar.foobar.name
and know that it doesn’t matter which model foobar is at that moment. (Since all foobars have a name attribute)
Is there a way to do this or do I have to test for it with responds_to? everytime I want to use it.
You can provide defaults by creating a base class that
FooandQuxextend. Instead ofyou could do something like
You could then create a default accessor method for the attributes you want to be consistent for those classes extending
Foobar.You can overload
nameas shown above inFoo, or omit it as shown inQux. Regardless, anameattribute will be available, even if it’s only the default fromFoobar.If you’re looking to create more of a contract through an interface or abstract class as is common in other languages, Ruby doesn’t support either. You can however use a mixin that you’d include in
FooandQuxto throw an Exception ifnameis not defined. Read an example of this sort of implementation here.Note on the chance these models are supposed to have an associated
namecolumn in the table, you will likely want to incorporateread_attribute(:name)somewhere in your overloadednamemethod. See the docs onread_attribute