On 4/26/06, robbie shepherd <robbie.shepherd@gmail.com>
wrote:>
> I have a form with about 30+ fields, which the client is wanting to
> separate into 3 pages/steps - just wondering what is the best way to go
> about this, specifically remembering data entered, from one page to
> another, and making sure the various bits of data are validated
> correclty, error messages outputted etc etc...
>
> is there a best practice method for doing this?
I had to do the exact same thing. I found two different articles regarding
how to implement this type of thing:
<
http://www.kylemaxwell.com/articles/2006/02/06/fun-with-single-table-inheritance>
and
<http://www.bigbold.com/snippets/posts/show/277>
I tried the first link but wasn''t able to get it to work (and I also
preferred the second method). I changed the second method to make it a bit
more dynamic. Here''s what I''m using right now, which also
does validation
on the fields before creating the new record (by the way, if anyone else has
any other methods for implementing multi-part forms, please post them!):
class UserController < ApplicationController
before_filter :clear_stage_errors, :get_partial_user_from_session
after_filter :save_partial_user_in_session
def initialize
# here we provide the names of the fields that we want to be validated
# at each stage, where stage1 corresponds to the fields listed in
@stages[0]
@stages = [ %w(first_name last_name address1 country city state zip_code
birth_date phone1 email),
%w(radio_stations personal_genres),
%w(live_performance_frequency),
%w(employment_experience ),
%w(some_field some_other_field)
]
end
def signup
case @request.method
when :post
# current_stage is stored in a hidden form field
@current_stage = @params[:current_stage].to_i
# if user hit the previous button, decrement the current stage
if @params[''imgPrevious.x'']
@current_stage -= 1
return;
end
@user.attributes = @params[''user'']
if (@current_stage >= @stages.length) &&
(valid_for_attributes(@user,
@stages[@current_stage - 1]))
if @user.save
# if we don''t reset the @user ivar to nil, whenever we access
the
signup
# form, it keeps repopulating the contents of the fields with the
previously
# entered information
@user = nil
# you might not want to reset the session here, if so, remove this
next line
reset_session
flash[''notice''] = "Signup successful"
redirect_to :action => :index, :controller => "site"
return
end
else
# move on to the next stage only if we can validate all the
attributes for the current stage
if (valid_for_attributes(@user, @stages[@current_stage - 1]))
@current_stage += 1
end
end
when :get
# since the request is a get, we fetch the first stage
@current_stage = 1
end
end
def get_partial_user_from_session
unless @session[''partial_user''].nil?
@user = @session[''partial_user'']
else
@user = User.new
end
end
def save_partial_user_in_session
unless @user.nil?
@session[''partial_user''] = @user
end
end
# Might be a good addition to AR::Base
def valid_for_attributes( model, attributes )
unless model.valid?
errors = model.errors
our_errors = Array.new
errors.each { |attr,error|
if attributes.include? attr
our_errors << [attr,error]
end
}
errors.clear
our_errors.each { |attr,error| errors.add(attr,error) }
return false unless errors.empty?
end
return true
end
end
in models/user.rb
class User < ActiveRecord::Base
validates_presence_of :first_name, :last_name, :address1, :city, :state,
:country, :zip_code, :phone1, :email, :birth_date, :radio_stations,
:personal_genres, :live_performance_frequency
end
in views/user/signup.rhtml:
<%= start_form_tag({:action=> "signup"} , { :name =>
''signupform'',
:multipart => true } ) %>
<%= hidden_field_tag "current_stage", @current_stage %>
<%= @flash[''notice''] %>
<%= render_partial "stage#{@current_stage}" %>
<div id="bottomNavigation" style="padding-top:10px;">
<% if @current_stage != 1 %>
<input type="image" name="imgPrevious"
src="/images/common/button_previous.gif" alt="Previous"
/>
<% end %>
<input type="image" name="imgNext"
src="/images/common/button_next.gif" alt="Next" />
</div>
<%= end_form_tag %>
and then place each of your stages with your text_fields, checkboxes, form
elements, etc into views/user/[_stage1.rhtml, _stage2.rhtml, _stage3.rhtml,
...] ie:
in _stage1.rhtml:
<table>
<tr>
<td><label for="first_name">First
Name:</label></td>
<td ><%= text_field ''user'',
''first_name'' %></td>
</tr>
<tr>
<td><label for="middle_initial">Middle
Initial:</label></td>
<td ><%= text_field ''user'',
''middle_initial'' %></td>
</tr>
</table>
good luck,
Mike
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://wrath.rubyonrails.org/pipermail/rails/attachments/20060426/1bd40253/attachment-0001.html