Is there a clever rails way to chain multiple forms together to collect all the info that I need before finally calling "save"? For example consider an app which needs to create a "Order" object which is tied to a "Contact" object which may or may already exist. Lets pretend we don''t want to save the order to the DB until the contact info is known and both objects must be saved atomically. We have a form for editing Orders, and a Form for editing Contacts. We call the Orders form first and obtain the info, now I want to stash the detail somewhere while I go and obtain the Contact data. What is a good way to serialise that data while we call the Contact form? Lots of apps like to stuff it in as a serialised hidden field so that you don''t have problems with multiple sessions at the same time - how might we go about this in Rails? Ed W
You could save it in the session or flash. On 12/20/05, Ed W <lists-XJavvHiACVh0ubjbjo6WXg@public.gmane.org> wrote:> Is there a clever rails way to chain multiple forms together to collect > all the info that I need before finally calling "save"? > > For example consider an app which needs to create a "Order" object which > is tied to a "Contact" object which may or may already exist. Lets > pretend we don''t want to save the order to the DB until the contact info > is known and both objects must be saved atomically. > > We have a form for editing Orders, and a Form for editing Contacts. We > call the Orders form first and obtain the info, now I want to stash the > detail somewhere while I go and obtain the Contact data. What is a good > way to serialise that data while we call the Contact form? Lots of apps > like to stuff it in as a serialised hidden field so that you don''t have > problems with multiple sessions at the same time - how might we go about > this in Rails? > > Ed W > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Kyle Maxwell wrote:>You could save it in the session or flash. > >But that''s going to be a problem when you have a user logged in and they open up several windows to your server, isn''t it? Ed W
El 20/12/2005, a las 02:59 PM, Ed W escribió:> Is there a clever rails way to chain multiple forms together to > collect all the info that I need before finally calling "save"?How about marshalling your objects using YAML and putting them into a hidden form field. Have never tried it, but ought to work. Patrice
On 12/21/05, Ed W <lists@wildgooses.com> wrote:> Kyle Maxwell wrote: > > >You could save it in the session or flash. > > > > > > But that's going to be a problem when you have a user logged in and they > open up several windows to your server, isn't it? > > Ed W > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >Not if you're smart about it. -- Kyle Maxwell Chief Technologist E Factor Media // FN Interactive kyle@efactormedia.com 1-866-263-3261 _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
Patrice Neff wrote:> El 20/12/2005, a las 02:59 PM, Ed W >escribigt; Is there a clever rails way to chain multiple forms together to >> collect all the info that I need before finally calling "save"? > > How about marshalling your objects using YAML and putting them into a > hidden form field. Have never tried it, but ought to work. > > Patrice_______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/railsI JUST WANT TO SAY I AM IN CHAOS. water purification system,Water Purification Equipment,Water Purification Plants http://www.51center.net/futian/en/index.htm -- Posted via http://www.ruby-forum.com/.
On Wed, Dec 21, 2005 at 08:13:57AM +0000, Ed W wrote:> Kyle Maxwell wrote: > > >You could save it in the session or flash. > > > > > > But that''s going to be a problem when you have a user logged in and they > open up several windows to your server, isn''t it?To save you from having to store all the form data in a hidden field, you could implement a ''session inside session'' approach, i.e. store your form data under a unique key in the user session. Each time a user submits the first of your forms, a new key has to be generated and kept in a hidden field on all following pages. The key now allows you to retrieve the correct order object from the user''s session, even if the user has opened more browser windows to your app. Jens -- Jens Krämer jk-UayuY8ajoWPk1uMJSBkQmQ@public.gmane.org
>To save you from having to store all the form data in a hidden field, >you could implement a ''session inside session'' approach, i.e. store >your form data under a unique key in the user session. > >Each time a user submits the first of your forms, a new key has to be >generated and kept in a hidden field on all following pages. The key >now allows you to retrieve the correct order object from the user''s >session, even if the user has opened more browser windows to your app. > >How does this compare with simply marshaling the data and putting that in a hidden text field on the form? Arguably the data is harder to forge if you leave it in the session, but I''m thinking that the validation is all done at the end and if there are problems we popup the correct screen for the user to correct (rinse and repeat until we are happy) Any pros/cons to either technique? Thanks Ed W
On 12/21/05, Ed W <lists@wildgooses.com> wrote:> > >To save you from having to store all the form data in a hidden field, > >you could implement a 'session inside session' approach, i.e. store > >your form data under a unique key in the user session. > > > >Each time a user submits the first of your forms, a new key has to be > >generated and kept in a hidden field on all following pages. The key > >now allows you to retrieve the correct order object from the user's > >session, even if the user has opened more browser windows to your app. > > > > > > How does this compare with simply marshaling the data and putting that > in a hidden text field on the form? > > Arguably the data is harder to forge if you leave it in the session, but > I'm thinking that the validation is all done at the end and if there are > problems we popup the correct screen for the user to correct (rinse and > repeat until we are happy) > > Any pros/cons to either technique? > > Thanks > > Ed W > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >I would use single table inheritance to achieve the results you desire. Make a base class called EmptyOrder, then an inherited class called PartlyCompletedOrder, then a class inherited from PartlyCompletedOrder called CompletedOrder. EmptyOrder has all of the instance methods you wish to have in this class, as well as a method called to_class, which takes a class name as an argument, and attempts to type cast the row to that class. PartlyCompletedOrder has some validations, and CompletedOrder has yet more validations. As should be apparent, you don't need exactly three classes in this system, 2...n will work. My one concern with this system is the associations. They will have to be particularly complex, as you may need to specify an association in the EmptyContact class for each class in the Order hierarchy, and vice versa. I haven't had to use this technique for multi-model forms yet. Let me know how it goes, should you choose this route. -- Kyle Maxwell Chief Technologist E Factor Media // FN Interactive kyle@efactormedia.com 1-866-263-3261 _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
>To save you from having to store all the form data in a hidden field, >you could implement a ''session inside session'' approach, i.e. store >your form data under a unique key in the user session. > >Each time a user submits the first of your forms, a new key has to be >generated and kept in a hidden field on all following pages. The key >now allows you to retrieve the correct order object from the user''s >session, even if the user has opened more browser windows to your app. > >I have thought about this a bit more and I like the idea. Actually this technique could be useful in lots of other areas, for example where you want to track the "redirect to previous" location, it would obviously be nice if this didn''t go wrong just because you were editing two things in seperate browser windows. The biggest issue I see is that the session is going to fill up with crud data? Assuming that the users in question are using the system day in and out then the session isn''t going to expire so the session will eventually fill up with huge amounts of dead data every time a transaction is aborted. Is there a smart way to handle this? I can imagine making the session a hash and storing a "last used" time as well as the object. Then perhaps every time we access the session we need to scan through for old data. It seems to incur a bit of overhead, but it''s not obvious how else to do it? Is is possible to build something which can "walk" every session on a timed basis and examine all the objects and remove anything which has expired? Any other suggestions? Ed W
Ed Wildgoose wrote:> >> To save you from having to store all the form data in a hidden field, >> you could implement a ''session inside session'' approach, i.e. store >> your form data under a unique key in the user session. >> Each time a user submits the first of your forms, a new key has to be >> generated and kept in a hidden field on all following pages. The key >> now allows you to retrieve the correct order object from the user''s >> session, even if the user has opened more browser windows to your app. >> >> > > I have thought about this a bit more and I like the idea. Actually this > technique could be useful in lots of other areas, for example where you > want to track the "redirect to previous" location, it would obviously be > nice if this didn''t go wrong just because you were editing two things in > seperate browser windows. > > The biggest issue I see is that the session is going to fill up with > crud data? Assuming that the users in question are using the system day > in and out then the session isn''t going to expire so the session will > eventually fill up with huge amounts of dead data every time a > transaction is aborted. > > Is there a smart way to handle this? I can imagine making the session a > hash and storing a "last used" time as well as the object. Then perhaps > every time we access the session we need to scan through for old data. > It seems to incur a bit of overhead, but it''s not obvious how else to do > it? > > Is is possible to build something which can "walk" every session on a > timed basis and examine all the objects and remove anything which has > expired? > > Any other suggestions?We just submit the form along and create a new (hidden) form on each page in the track. I.e., in the controller: @order = Order.new(params[:order]) (now you can validate it, whatever, but not save it until they commit the order in another method) in the pages in the track: <form action="error" method="post" name="order_data"> <% @order.attributes.each do |column| %> <input type=hidden name="order[<%= column[0] %>]" value="<%= column[1] %>"> <% end %> Notice the action is invalid. We have two buttons, edit and submit. JS overrides the action name and submits for us either backwards or forwards in the track. With no JS support they go to the error page. BTW- Be careful what you store on the web server if you are subject to Visa or MC audits. You are not supposed to store credit card numbers on a public facing server, for example. And, you never should store CSC card #''s (those 3 or 4 digits on the back of the card). I noticed the Rails book uses examples where they store credit card numbers and such, which can be a no-no in many cases. Oh, and be careful what method you use to store sessions. We switched to storing sessions in the SQL backend, and things broke. We had to go back to files. This seems to be especially true for sessions which store larger chunks of data. Phil