Hello, I need some advice. I want to create a 5 step form with a lot of radio buttons, checkboxes and select lists. So there are many different "results" possible. Now I wonder what''s the best way to do that with Rails. Should I store all the values in the database or in YAML or something else, what''s the best practice for such a problem? What about the wizard thing, should I use the user''s session to track the progress? tia, bye Wolfgang
Wolfgang, Im no Rails expert, but istm that the design should be an array of arrays - each subarray has state-condition-destination This back in the model layer, and supporting calculations can be there. This is just a state machine structure that keeps track of where you are. Of course, if each screen needs complex data displayed, you must either generate or store that. In the case of complex data, I start thinking about a database table along the lines of the array mentioned, except that the array elements become columns in the table, and the specialized data for each screen, or the precursors to it, are in further columns of the state machine row. I am not a database designer, but I imagine a compact representation would be just the n data items in columns, and then tables to look them up. Since we are working with Ruby-Rails here, it would be tempting to be able to create database tables on the fly, but thats not SOP. And that would be a state machine that was modifiable-addable by the user, which might give you advantages if you had to program a lot of these wizards. The state - condition - destination triplet is the classical way to go... jb ----- Original Message ----- From: "Wolfgang Klinger" <wolfgang-qRyVSpHmpvQsV2N9l4h3zg@public.gmane.org> To: <rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org> Sent: Monday, May 09, 2005 10:30 AM Subject: [Rails] Wizard style form advice> > Hello, > > I need some advice. > > I want to create a 5 step form with a lot of radio buttons, checkboxes > and select lists. So there are many different "results" possible. > > Now I wonder what''s the best way to do that with Rails. Should I store > all the values in the database or in YAML or something else, what''s > the best practice for such a problem? > > What about the wizard thing, should I use the user''s session to track > the progress? > > > tia, bye > Wolfgang > > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On 5/10/05, Wolfgang Klinger <wolfgang-qRyVSpHmpvQsV2N9l4h3zg@public.gmane.org> wrote:> What about the wizard thing, should I use the user''s session to track > the progress?In my mind, the session is the correct place for this until the final commit to the database if you don''t want to have half-entered data in the database. I''d store unsaved model objects in the session as I went along instead of an ad-hoc data structure such as request.parameters, its going to be easier to evolve (if you keep in mind needing to clear the session if the model changes). If the form involves payment though, you''ll probably want to store it all in the database as you go along so you can have an audit trail if things go wrong. Leon
First off, you need to ask yourself some questions: 1. Does the user need to complete the wizard in one session, or can they finish halfway through and come back? If the answer is that they have to finish the form in one session, then no persistence is required and you can store the form state in memory (I''m more OO than array oriented and would suggest having a wizard object or something to hold the state - all those [] confuse me after a while). If you need to save the wizards state, you definatley need to give careful thought as to the structure of what''s being saved. 2. How often are the different types of values going to change? If the answer is "never" then putting it in a YAML configuration file is probably OK. The more you want to change these values, the more benefit there is in placing them in the DB and generating a UI for you to administer them. In general, when creating wizards I''d suggest drawing them up on a piece of paper to work the flow out. Detail validaition carefully (everyone hates those forms that only error on step 5 and make you go all the way back to step 1). As a general UI point, being able to review all 5 steps on one page at the end is a nice touch (which is easy to do if you''re rendering your wizard-steps using render_partial). Happy to provide more advice if you have some more concrete examples... sam On 5/9/05, leon breedt <bitserf-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On 5/10/05, Wolfgang Klinger <wolfgang-qRyVSpHmpvQsV2N9l4h3zg@public.gmane.org> wrote: > > What about the wizard thing, should I use the user''s session to track > > the progress? > In my mind, the session is the correct place for this until the final > commit to the database if you don''t want to have half-entered data in > the database. > > I''d store unsaved model objects in the session as I went along instead > of an ad-hoc data structure such as request.parameters, its going to > be easier to evolve (if you keep in mind needing to clear the session > if the model changes). > > If the form involves payment though, you''ll probably want to store it > all in the database as you go along so you can have an audit trail if > things go wrong. > > Leon > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- sam http://www.magpiebrain.com/
leon breedt <bitserf-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:> On 5/10/05, Wolfgang Klinger <wolfgang-qRyVSpHmpvQsV2N9l4h3zg@public.gmane.org> wrote: >> What about the wizard thing, should I use the user''s session to track >> the progress? > In my mind, the session is the correct place for this until the final > commit to the database if you don''t want to have half-entered data in > the database. > > I''d store unsaved model objects in the session as I went along instead > of an ad-hoc data structure such as request.parameters, its going to > be easier to evolve (if you keep in mind needing to clear the session > if the model changes).This is a totally different project, but the same problem. I have an object with lots and lots of attributes (MemberProfile). The form is quite large. Currently it''s several pages being filled out by hand. At this point in my project I have it all on one form. The attributes are validated by the model and errors are highlighted as they should be. If I break this up into multiple forms/pages (as it probably should be) and store the member_profile in progress in the session, it seems like I''d loose the model validations. I wouldn''t be validating until the last form when I save the object. I''d like to be able to validate the individual forms as the user moves through the steps of filling out the profile. -- doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org
speechexpert wrote:> Wolfgang, > Im no Rails expert, but istm that the design should be an array of arrays - > each subarray has state-condition-destination > This back in the model layer, and supporting calculations can be there. > This is just a state machine structure that keeps track of where you are. > Of course, if each screen needs complex data displayed, you must either > generate or store that. > In the case of complex data, I start thinking about a database table along > the lines of the array mentioned, except > that the array elements become columns in the table, and the specialized > data for each screen, or the precursors to it, are in > further columns of the state machine row. I am not a database designer, but > I imagine a compact representation would be > just the n data items in columns, and then tables to look them up. > Since we are working with Ruby-Rails here, it would be tempting to be able > to create database tables on the fly, but > thats not SOP. And that would be a state machine that was modifiable-addable > by the user, which might give you > advantages if you had to program a lot of these wizards. > The state - condition - destination triplet is the classical way to go...Along these lines, is there any plan to write a Ruby version of the State-Map Compiler? http://smc.sourceforge.net/ Or does Ruby make it "just too easy", as usual? Cheers, Jim
Doug, I had a very similar problem, also with a very large "member" object. I went to #rubyonrails on IRC and asked, and the answer I got was basically, "don''t do multi-page forms, look for something simpler". At first I really didn''t like that answer. After giving it a lot of thought, I realized that it was possible in my situation. I basically had to ask for membership info(page1) and billing info(page2). I was planning on a single member object. Then it hit me, why not have a separate billing info object? The only problem with this is that a member object could be created and the user could leave and not create the billing info object. That can be handled by asking that info again on the next login. There will always be those cases where you MUST do a wizard, but if possible I''m breaking them down into a series of smaller forms. - Philip On 5/10/05, Doug Alcorn <doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org> wrote:> This is a totally different project, but the same problem. I have an > object with lots and lots of attributes (MemberProfile). The form is > quite large.
On 10/05/2005, at 10:35 PM, Doug Alcorn wrote:> This is a totally different project, but the same problem. I have an > object with lots and lots of attributes (MemberProfile). The form is > quite large. Currently it''s several pages being filled out by hand. > At this point in my project I have it all on one form. The attributes > are validated by the model and errors are highlighted as they should > be. > > If I break this up into multiple forms/pages (as it probably should > be) and store the member_profile in progress in the session, it seems > like I''d loose the model validations. I wouldn''t be validating until > the last form when I save the object. I''d like to be able to validate > the individual forms as the user moves through the steps of filling > out the profile.You''ll have to write some of your own functions if you want to bend AR::Validations to do incremental validation. Here''s some code: http://rafb.net/paste/results/5balol20.html You have to use clear_stage_errors in each action of the multi-step form. - tim lucas aviditybytes.com
On 11/05/2005, at 10:10 AM, Tim Lucas wrote:> You''ll have to write some of your own functions if you want to bend > AR::Validations to do incremental validation.Also, if you want to save the object at each step (for an audit trail or for usage tracking) you could probably do something like: def partial_user.table_name ''user_registrations''; end partial_user.save(false) - tim lucas
On Monday 09 May 2005 19:30, Wolfgang Klinger wrote:> I want to create a 5 step form with a lot of radio buttons, > checkboxes and select lists. So there are many different "results" > possible.[snip]> What about the wizard thing, should I use the user''s session to > track the progress?I''m assuming that you don''t need an arbitrary(!) number of interrelated objects. Given that, I have two untested (by me) suggestions. (1) Put input elements for all options on *each* of the pages, but on each one display only a subset of the options. From the user''s point-of-view, the pages are different, from the point-of-view of your app they''re all the same. Decide which page to return to the user based on a request parameter such as "page=2". (2) Similar to the above, use only one real page, but selectively show and hide options using JavaScript. Michael -- Michael Schuerig Nothing is as brilliantly adaptive mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org as selective stupidity. http://www.schuerig.de/michael/ --A.O. Rorty, The Deceptive Self
Tim Lucas <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> writes:> You''ll have to write some of your own functions if you want to bend > AR::Validations to do incremental validation. > > Here''s some code: > http://rafb.net/paste/results/5balol20.html > > You have to use clear_stage_errors in each action of the multi-step > form.This is very helpful. As a Ruby Nuby, it''s interesting to see how others solve problems with it. That example is easy to follow and extend to other areas. Thanks. -- doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org
On 11/05/2005, at 11:14 PM, Doug Alcorn wrote:> Tim Lucas <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> writes: > >> You''ll have to write some of your own functions if you want to bend >> AR::Validations to do incremental validation. >> >> Here''s some code: >> http://rafb.net/paste/results/5balol20.html >> >> You have to use clear_stage_errors in each action of the multi-step >> form. > > This is very helpful. As a Ruby Nuby, it''s interesting to see how > others solve problems with it. That example is easy to follow and > extend to other areas. Thanks.No problemo. And for those still wanting the code snippet, I''ve posted it to bigbold.com (thanks Peter Cooper): http://www.bigbold.com/snippets/posts/show/277 I love how easy it is to come up with your own solutions to problems in Ruby and Rails. =) - tim lucas If you''re reading Mr Cooper: An interesting project would be to add bigbold.com/snippet support to typo, so when you post a code snippet to your blog it simultaenously posts to bigbold.com/snippets as well.
Doug and Philip, There is a patch right now that Joseph Hosteny and I developed that will solve this problem: http://dev.rubyonrails.com/ticket/1196 The final solution (scroll down to the bottom for the discussion) is a small modification to ActiveRecord that allows for conditional validations, like this: class MyModel < ActiveRecord::Base def after_step_one; self.step > 1; end def after_step_two; self.step > 2; end validates_uniqueness_of :login, :if => :after_step_one validates_presence_of :name, :if => :after_step_two end I''m not sure when this patch will be released, but I''m hoping on the next release. Duane Johnson (canadaduane) On May 10, 2005, at 1:21 PM, Philip Gatt wrote:> Doug, > > I had a very similar problem, also with a very large "member" object. > I went to #rubyonrails on IRC and asked, and the answer I got was > basically, "don''t do multi-page forms, look for something simpler". > > At first I really didn''t like that answer. After giving it a lot of > thought, I realized that it was possible in my situation. > > I basically had to ask for membership info(page1) and billing > info(page2). I was planning on a single member object. Then it hit me, > why not have a separate billing info object? The only problem with > this is that a member object could be created and the user could leave > and not create the billing info object. That can be handled by asking > that info again on the next login. > > There will always be those cases where you MUST do a wizard, but if > possible I''m breaking them down into a series of smaller forms. > > - Philip > > On 5/10/05, Doug Alcorn <doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org> wrote: > >> This is a totally different project, but the same problem. I have an >> object with lots and lots of attributes (MemberProfile). The form is >> quite large. >> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Duane Johnson <duane.johnson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> writes:> class MyModel < ActiveRecord::Base > def after_step_one; self.step > 1; end > def after_step_two; self.step > 2; end > > validates_uniqueness_of :login, :if => :after_step_one > validates_presence_of :name, :if => :after_step_two > end > > I''m not sure when this patch will be released, but I''m hoping on the > next release.awesome! -- doug-jGAhs73c5XxeoWH0uzbU5w@public.gmane.org
Hi! On Thu, 12 May 2005, Tim Lucas wrote the following:> And for those still wanting the code snippet, I''ve posted it to > bigbold.com (thanks Peter Cooper): > http://www.bigbold.com/snippets/posts/show/277Thanks to you and all the others for their valuable input! kind regards Wolfgang