Reputation: 581
I have three fields in one form and two fields in another (same as the earlier form, but just missing one field). I want to validate only two fields in the smaller form, but the issue is that it is validating all the three.
I have written the following logic:
**
class User < ActiveRecord::Base
validate :validate_form #for form with 2 fields
private
def validate_form
if :classify_create
self.errors.add(:weight, "need weight") if weight.blank?
self.errors.add(:height, "need height") if height.blank?
end
end
# Validations of attributes (for form with three fields)
validates :weight, :presence => true
validates :height, :presence => true
validates :gender, :presence => true
end
**
and this is my controller action: basically I have written two separate creates:
**# for form with two fields
def classify
@user = User.new
@title = "Classify"
end
def classify_create
@user = User.where("weight = ? and height = ?", params[:weight] ,params[:height])
end
# for form with three fields
def new
@user = User.new
@title = "Train"
end
def create
@user = User.new(params[:user])
if @user.save
redirect_to @user
else
@title = "Train"
render 'new'
end
end**
When I submit to the two field form, it gives me an error for gender too and redirects to the page with form having three fields. How should I go about it?
Any help will be appreciated.
Regards, Arun
Upvotes: 1
Views: 736
Reputation: 6682
First, I would not use classify
as a method name. You may conflict with a core inflector provided by ActiveSupport. Call it classification
or something.
Second, your validation is running on if @user.save
in the create
method.
In classify_create
you use User.where(...)
which is a finder method. You're pulling a matching record and setting it to @user
. This does not run validation, yet you receive validation errors. You are posting to create
, not classify_create
. Bad routes will cause this.
Let's address conditional validation first. In your User
model, create a variable to act as a bypass switch for your gender validation. Then tell your validation to check if this bypass switch is false before running:
User < ActiveRecord::Base
attr_accessor :skip_gender # defaults to nil (false)
# ...
validates :gender, :presence => true, :if => :validate_gender? # validate if...
# ...
private
def validate_gender?
!self.skip_gender # true = run validation, false = skip validation
end
# ...
end
Next, clean up your controller. Write two create
methods, one setting the switch, one not. (This isn't DRY):
def new_classification
# for form with two fields
@user = User.new
@title = "Classify"
end
def new
# for form with three fields
@user = User.new
@title = "Train"
end
def create
@user = User.new(params[:user])
if @user.save
redirect_to @user
else
render :action => 'new' # render three-field form
end
end
def create_classification
@user = User.where(:weight => params[:weight], :height => params[:height])
# ... do something with @user ...
@user.skip_gender = true # tell @user to skip gender validation
if @user.save
redirect_to @user
else
render :action => 'new_classification' # render two-field form
end
end
Next, adjust config/routes.rb
to specify routes to your custom methods.
resources :users do
member do
get 'new_classification', :to => 'users#new_classification', \
:as => :new_classification_for
post 'create_classification', :to => 'users#create_classification', \
:as => :create_classification_for
end
end
Now change your two-field form view. Specify where your form is submitted to.
<%= form_for @user, :url => create_classification_for_user_url(@user) do |f| %>
That should get you by with what you have...
Upvotes: 3
Reputation: 434945
Your problem is two-fold:
The easy solution is to kludge around the limitations with a separate controller:
def create_genderless
# Force the issue to an explicit "unknown" state so that
# "unknown" and "missing" can be differentiated.
params[:user][:gender] = 'U'
# And then punt to the existing `create` method.
create
end
Then a bit more validation in your model for good measure
class User < ActiveRecord::Base
validates :gender, :inclusion => { :in => %w[M F U] }
#...
end
Then update your forms to use UserController#create
or UserController#create_genderless
as appropriate.
Upvotes: 0