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
1. Only save the Source and Resource if both are valid 2. Not duplicate a bunch of validation logic in the controller
Anyone have ideas for how I can accomplish this?
Thanks in advance!
Ben