disposable
disposable copied to clipboard
Using a twin with nested properties to decorate a flat model
Hey Nick, long time no talk, you may not even remember me haha! I've been busy with other stuff and had to pause my work using trailblazer, but I'm back at it now.
Here is the deal, suppose I have the following flat model (no nested objects):
Song = Struct.new(:title, :track, :length)
But from my form I receive this nested hash:
{
song: {
title: 'Roxanne',
details: {
track: 3,
length: '4:10'
}
}
So I have this form that maps nicely to the nested hash:
class SongForm < Reform::Form
property :title
property :details do
property :track
property :length
end
# validations...
end
Now, I don't want to do the mapping nested hash -> flat model
directly in my form, the form should not know about this. So I want introduce a twin that the form will use to do the mapping and syncing, like this:
params = {
song: {
title: 'Roxanne',
details: {
track: 3,
length: '4:10'
}
}
twin = SongTwin.new(Song.new)
form = SongForm.new(twin)
if form.validate(params)
# will sync to the twin and call save on it
# the twin will sync to the model (mapping the nested hash to the flat model) and then call save it
form.save
end
So I need something close to what I can do with nested in Representable (in fact, I stole this example from its documentation), but with the twin getters and setters, since I plan on using the twin to implement simple business logic:
class SongTwin < Disposable::Twin
feature Sync
feature Nested
property :title
nested :details do
property :track
property :length
end
# business logic using the getters and setters (including the nested ones)
end
I believe that currently the simpler way to do this would be to override the sync
method of the twin:
def sync
super do |hash|
model.title = hash[:title]
model.track = hash[:details][:track]
model.length = hash[:details][:length]
end
end
But this is obviously not a nice solution and it doesn't work for reading...
This relates to this Reform issue: https://github.com/apotonick/reform/issues/277
Maybe I could use the Parent
feature to to delegate the nested twin setters/getters to the parent twin... But still, it would required lots of delegations for a big twin.
Now, this is funny, because we were just needing the same thing with @danieldraper and came to the conclusion that something like nested
, plus :getter
and :setter
could be helpful in Disposable! :laughing:
And, of course I remember you, good to have you back, my lost son! :beers:
Cool, so we're in sync! Also, with this implemented in Disposable, it could be used in Reform too, right? (As in the Reform issue I referenced)
Yes, a form object is simply a twin with validation semantics.