Created
February 21, 2010 13:34
-
-
Save ilake/310314 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#<a href="http://ow.ly/18z1T">RoR Multi-step forms</a> | |
private | |
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 | |
#To ensure the errors are cleared out properly on each request add a before_filter with the following: | |
def clear_stage_errors | |
unless @session['partial_user'].nil? | |
@session['partial_user'].errors.clear | |
end | |
end | |
=begin | |
You can use | |
get_partial_user_from_session | |
and | |
save_partial_user_in_session | |
as before and after filters, respectively, so you only have to reference @user in your multi-step controller. | |
=end | |
#A clean way to arrange the view is to have each step in its own partial, and set a variable such as | |
@current_stage | |
#in your controller, then in your view just do something like: | |
<%= start_form_tag({:action=> "signup"} , { :name => 'signupform' }) %> | |
<%= hidden_field_tag "changeCountry" %> | |
<%= hidden_field_tag "current_stage", "#{@current_stage}"%> | |
<h2>Registration Process</h2> | |
<%= @flash['notice'] %> | |
<%= render_partial "#{@current_stage}" %> | |
<%= end_form_tag %> | |
#Your signup controller action could something similar to this: | |
def signup | |
case @request.method | |
when :post | |
@current_stage = @params['current_stage'] | |
if @current_stage == "stage1" | |
@user.attributes = @params['user'] | |
@current_stage = "stage2" if valid_for_attributes(@user,["login","attribute2"]) | |
end | |
elsif @current_stage == "stage2" | |
@user.attributes = @params['user'] | |
@current_stage = "stage3" if valid_for_attributes(@user,["attribute3","attribute4"]) | |
elsif @current_stage == "stage3" | |
@user.attributes = @params['user'] | |
if @user.save | |
@session[:user] = User.authenticate(@user.login, @params['user']['password']) | |
flash['notice'] = "Signup successful" | |
redirect_to :action => "home" | |
end | |
end | |
when :get | |
@current_stage = "stage1" | |
end | |
end | |
#========================================== | |
=begin | |
Comments on this post | |
bmarini posts on May 19, 2008 at 12:56 | |
I took your partial validation idea and included it in AR Base | |
=end | |
module ActiveRecord | |
module Validations | |
module Partial | |
def valid_for_attributes?( *attr_names ) | |
return validate_for_attributes(attr_names) | |
end | |
def validate_for_attributes( *attr_names ) | |
attr_names.map! {|a| a.to_s } | |
unless valid? | |
our_errors = Array.new | |
errors.each { |attr,error| | |
if attr_names.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 | |
end | |
end | |
ActiveRecord::Base.class_eval do | |
include ActiveRecord::Validations::Partial | |
end | |
=begin | |
cgunther posts on Jul 02, 2009 at 11:40 | |
bmarini, I think there is a bug in your code. | |
When I called: | |
=end | |
@order.valid_for_attributes? 'first_name', 'last_name' | |
=begin | |
It always passed validation. The error was the asterisk in front of attr_names on validate_for_attributes. It was being passed an array as the first attribute and when you run map! on it, it was converting the entire array to a single string (first_namelast_name). | |
Here's the code that works for me: | |
=end | |
module ActiveRecord | |
module Validations | |
module Partial | |
def valid_for_attributes?( *attr_names ) | |
return validate_for_attributes(attr_names) | |
end | |
def validate_for_attributes( attr_names ) | |
attr_names.map! {|a| a.to_s } | |
unless valid? | |
our_errors = Array.new | |
errors.each { |attr,error| | |
if attr_names.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 | |
end | |
end | |
ActiveRecord::Base.class_eval do | |
include ActiveRecord::Validations::Partial | |
end | |
#The main difference is that if you call validate_for_attributes directly, you have to pass it an array. | |
#Chris Gunther |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment