views:

60

answers:

1

I have an ActiveRecord model with several virtual attribute setters. I want to build an object but not save it to the database. One setter must execute before the others. How to do?

As a workaround, I build the object in two steps

@other_model = @some_model.build_other_model
@other_model.setup(params[:other_model)

Where setup is:

class OtherModel < ActiveRecord::Base
  def setup(other_params)
     # execute the important_attribute= setter first
    important_attribute = other_params.delete(:important_attribute)

     # set the other attributes in whatever order they occur in the params hash
    other_params.each { |k,v| self.send("#{k}=",v) }
  end
end

This seems to work, but looks kludgy. Is there a better way?

EDIT

per neutrino's suggestion, I added a method to SomeModel:

class SomeModel < ActiveRecord::Base
  def build_other_model(other_params)
    other_model = OtherModel.new(:some_model=>self)
    other_model.setup(other_params)
    other_model
  end
end
+1  A: 

It's a good thing that you have this manipulations done in an OtherModel's method, because you can just call this method and not worry about the order of assignments. So I would leave this part but just call it from a SomeModel's method:

class SomeModel < ActiveRecord::Base
  def build_other_model(other_params)
    other_model = build_other_model
    other_model.setup(other_params)
    other_model
  end
end

So then you would have

@other_model = @some_model.build_other_model(params[:other_model])
neutrino
Thanks, this set me on the right road, although calling `build_other_model` from itself didn't work --- using `OtherModel.new(:some_model=>self) did.
zetetic