Hi all,
I’m trying my best to adhere to the thin controller/fat model
philosophy - in particular, I’m trying to make sure my validation
stays inside my models, so it can be reused in multiple places.
My current problem is that I have an action that creates several
objects all at once. In my app, there are Sources (which represent an
entire web site) and Resources (which map to a single URL). Each
Source has_many Resources (so each Resource belongs_to a Source).
In my action, I need to create both a Source and a linked Resource.
However, each has some validation that needs to occur. If either the
Source or Resource has a problem, neither should be created.
My initial thought was to use a transaction. I would use save! so that
if anything went wrong, I could just print out the error in the flash.
My controller action contained code that looked something like this:
begin
Source.transaction do
@resource =Resource.new(:source => Source.new(:name =>
params[:name]), :url => params[:url])
@source = @resource.source
@source.save!
@resource.save!
end
do some stuff
rescue ActiveRecord::RecordInvalid, AssertionFailure => error
# put the error message in the flash
render :action => ‘new’
end
If there is something wrong in Source (e.g. the name is empty), this
works fine - it prints out the nice error message I have in the Source
model.
However, if something is wrong in the Resource, Source just gives the
following error: ‘Validation failed: Resources is invalid’. That’s not
very helpful to the user.
Of course, I can do @resource.save! first, but if there is a problem
with the Source, ActiveRecord complains that the source_id cannot be
null (since it could not save).
Clearly my approach is very wrong here. My goal is to
- Only save the Source and Resource if both are valid
- Not duplicate a bunch of validation logic in the controller
Anyone have ideas for how I can accomplish this?
Thanks in advance!
Ben