Making #composed_of more useful
Update: my patch finally got added to edge rails.
Active Record allows you to abstract fields into an aggregate object by using the composed\_of
declaration. This is handy, but the current implementation can be a real pain.
The first and somewhat trivial issue is the composed_of
declaration builds a string and evals it to define the attribute accessors. It’s not a big deal, but it’s dirty. The second issue is that aggregate objects are not easy to manipulate in Rails, especially in forms.
Fixing it
So, I’ve written a plugin that overrides the Active Record implementation of composed\_of
, which allows you to specify a block to convert incoming parameters to the correct type.
Personally, this has been most helpful when using the Money gem:
If \#balance=
receives anything besides a Money
object, it will call the block to try to convert the parameter to a Money
object.
And now it can transparently be used in forms:
This can even be used for more advanced aggregations:
A user can now be created from a hash:
I didn’t quite realize all the implications of this extension until I was writing up the docs for this plugin. Active Record magically does type casting for a limited set of types, namely dates and numbers. But this essentially allows you to have a form of type casting for any attribute. Interesting…
Installation
This has also been submitted as a patch to the Rails trac but hasn’t been accepted yet.
script/plugin install http://source.collectiveidea.com/public/rails/plugins/composed_of_conversion