I''ve recently upgraded to rails 2.0. Previously all my controllers were
traditional :controller/:action/:id based. I''ve now decided to go down
the REST route for new controllers etc.
So I''ve got a controller to do the create method for two models:
Licensee and licensee_address together in one form
The form tags looks like:
<% form_for([:agent, @licensee]) do |f| %>
.....
<% fields_for(@licensee_address) do |fl| %>
and the controller code for the posted data looks like:
# POST /agent/licensees
# POST /agent/licensees.xml
def create
@licensee = Licensee.new(params[:licensee])
@licensee.active = true
@licensee.agent = @auth_agent
@licensee_address = LicenseeAddress.new(params[:licensee_address])
@licensee_address.licensee = @licensee
respond_to do |format|
begin
Licensee.transaction do
@licensee.save!
@licensee_address.save!
# must assign a unique licensee ref
@licensee.licensee_ref = "%s%04d" %
[@licensee.name[0,3],@licensee.id]
@licensee.active = true
@licensee.save!
end
flash[:notice] = ''Licensee was successfully created.''
format.html { redirect_to(agent_licensees_url) }
format.xml { render :xml => @licensee, :status => :created,
:location => @licensee }
rescue ActiveRecord::RecordInvalid => e
#make sure we catch any validation errors on the address
@licensee_address.valid?
format.html { render :action => "new" }
format.xml { render :xml => @licensee.errors, :status =>
:unprocessable_entity }
end
end
end
Which all works splendidly if there are no validation errors. However,
if the are validation errors in the licensee_address, I have problems.
The licensee record was (temporarily) saved OK to the database so gets a
valid id and is no longer a "new" record. The saving of the
licensee_address fails. The transaction is rolled back so the database
is OK.
The problem comes with re-rendering the form to show the errors. The
licensee now looks like a valid record from the database and so the form
tag renders this as if it should post to an update method (i.e with a
PUT method and a valid id. This is clearly wrong. If I now correct the
error on the form and resubmit, the update method gets called and the
whole thing blows up!
Is there any way to tell an activerecord object that it was not really
saved to the database as it was rolled back? Is there any nice way to do
this kind of thing?
Cheers,
Gary.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
stephen.celis-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2008-Jan-20 14:42 UTC
Re: REST Validation dilemma
You could check the validity of both items before saving. if @licensee.valid? and @licensee_address.valid? ... On Jan 20, 8:14 am, Gary Doades <g...-UVRRe/+0hzLQXOPxS62xeg@public.gmane.org> wrote:> I''ve recently upgraded to rails 2.0. Previously all my controllers were > traditional :controller/:action/:id based. I''ve now decided to go down > the REST route for new controllers etc. > > So I''ve got a controller to do the create method for two models: > Licensee and licensee_address together in one form > > The form tags looks like: > > <% form_for([:agent, @licensee]) do |f| %> > ..... > <% fields_for(@licensee_address) do |fl| %> > > and the controller code for the posted data looks like: > > # POST /agent/licensees > # POST /agent/licensees.xml > def create > @licensee = Licensee.new(params[:licensee]) > -JvV4GCjhi6dIi0J7XieuPw@public.gmane.org = true > -JvV4GCjhi6eWnvMS3xHScg@public.gmane.org = @auth_agent > @licensee_address = LicenseeAddress.new(params[:licensee_address]) > @licensee_address.licensee = @licensee > > respond_to do |format| > begin > Licensee.transaction do > -JvV4GCjhi6ezOeKtxYPyNA@public.gmane.org! > @licensee_address.save! > # must assign a unique licensee ref > -JvV4GCjhi6ex/+Ph+b8bcbNAH6kLmebB@public.gmane.org_ref = "%s%04d" % > [@licensee.name[0,3],@licensee.id] > -JvV4GCjhi6dIi0J7XieuPw@public.gmane.org = true > -JvV4GCjhi6ezOeKtxYPyNA@public.gmane.org! > end > flash[:notice] = ''Licensee was successfully created.'' > format.html { redirect_to(agent_licensees_url) } > format.xml { render :xml => @licensee, :status => :created, > :location => @licensee } > rescue ActiveRecord::RecordInvalid => e > #make sure we catch any validation errors on the address > @licensee_address.valid? > format.html { render :action => "new" } > format.xml { render :xml => @licensee.errors, :status => > :unprocessable_entity } > end > end > end > > Which all works splendidly if there are no validation errors. However, > if the are validation errors in the licensee_address, I have problems. > > The licensee record was (temporarily) saved OK to the database so gets a > valid id and is no longer a "new" record. The saving of the > licensee_address fails. The transaction is rolled back so the database > is OK. > > The problem comes with re-rendering the form to show the errors. The > licensee now looks like a valid record from the database and so the form > tag renders this as if it should post to an update method (i.e with a > PUT method and a valid id. This is clearly wrong. If I now correct the > error on the form and resubmit, the update method gets called and the > whole thing blows up! > > Is there any way to tell an activerecord object that it was not really > saved to the database as it was rolled back? Is there any nice way to do > this kind of thing? > > Cheers, > Gary.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thanks for the suggestion. Yes, I could, but my example was over simplified to save space. My point is that I could have any number of operations/models in the transaction and any one of them could cause an exception. I was just wondering if there was a more general way of doing this is a safe fashion whilst still adhering to "standard" principles. Cheers, Gary. stephen.celis-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:> You could check the validity of both items before saving. > > if @licensee.valid? and @licensee_address.valid? > ... > > On Jan 20, 8:14 am, Gary Doades <g...-UVRRe/+0hzLQXOPxS62xeg@public.gmane.org> wrote: >> I''ve recently upgraded to rails 2.0. Previously all my controllers were >> traditional :controller/:action/:id based. I''ve now decided to go down >> the REST route for new controllers etc. >> >> So I''ve got a controller to do the create method for two models: >> Licensee and licensee_address together in one form >> >> The form tags looks like: >> >> <% form_for([:agent, @licensee]) do |f| %> >> ..... >> <% fields_for(@licensee_address) do |fl| %> >> >> and the controller code for the posted data looks like: >> >> # POST /agent/licensees >> # POST /agent/licensees.xml >> def create >> @licensee = Licensee.new(params[:licensee]) >> @licensee.active = true >> @licensee.agent = @auth_agent >> @licensee_address = LicenseeAddress.new(params[:licensee_address]) >> @licensee_address.licensee = @licensee >> >> respond_to do |format| >> begin >> Licensee.transaction do >> @licensee.save! >> @licensee_address.save! >> # must assign a unique licensee ref >> @licensee.licensee_ref = "%s%04d" % >> [@licensee.name[0,3],@licensee.id] >> @licensee.active = true >> @licensee.save! >> end >> flash[:notice] = ''Licensee was successfully created.'' >> format.html { redirect_to(agent_licensees_url) } >> format.xml { render :xml => @licensee, :status => :created, >> :location => @licensee } >> rescue ActiveRecord::RecordInvalid => e >> #make sure we catch any validation errors on the address >> @licensee_address.valid? >> format.html { render :action => "new" } >> format.xml { render :xml => @licensee.errors, :status => >> :unprocessable_entity } >> end >> end >> end >> >> Which all works splendidly if there are no validation errors. However, >> if the are validation errors in the licensee_address, I have problems. >> >> The licensee record was (temporarily) saved OK to the database so gets a >> valid id and is no longer a "new" record. The saving of the >> licensee_address fails. The transaction is rolled back so the database >> is OK. >> >> The problem comes with re-rendering the form to show the errors. The >> licensee now looks like a valid record from the database and so the form >> tag renders this as if it should post to an update method (i.e with a >> PUT method and a valid id. This is clearly wrong. If I now correct the >> error on the form and resubmit, the update method gets called and the >> whole thing blows up! >> >> Is there any way to tell an activerecord object that it was not really >> saved to the database as it was rolled back? Is there any nice way to do >> this kind of thing? >> >> Cheers, >> Gary. > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---