Rails: Using form fields that are unassociated with a model in validations
Solution 1
Don't let params sneak up to the model. There's no point of having a controller in that case. Instead, checkout this episode from Railscasts that talks about virtual attributes that do not go into the database but can still be used for validations.
You don't need a corresponding model attribute for the virtual attributes. Define attributes local to the class such as @no_fairways
that hold the state.
class ScoreCard < ActiveRecord::Base
# define attributes and accessors for both fields
attr_accessor :no_fairways, :no_girs
..
end
Now inside you form, you could just write:
<% form_for @scorecard %>
<%= f.check_box :no_fairways %>
<% end %>
Solution 2
Found the solution, thanks for the lingo though, "virtual attribute" helped with the google searchin.
The cleanliest way to accomplish this is to create attributes that are not part of the database but still part of the model. In my case I put this into the model:
attr_accessor :no_fairways
attr_accessor :no_girs
That easy! Now @scorecard.no_fairways
and @scorecard.no_girs
act just like any other attribute but aren't part of the database.
Jay
Updated on July 18, 2022Comments
-
Jay almost 2 years
In a Ruby on Rails application I am trying to use information from fields that are not associated with the model in validation.
Here is part of the model as an example (the whole model has gotten kinda big):
class Scorecard < ActiveRecord::Base belongs_to :course belongs_to :user validate :attributes_consistency def attributes_consistency # Executed for all scorecards. Checks if the user completed the hole attributes correctly if ( params[:no_fairways] and any_fairways? and !only_nine? ) or ( params[:no_fairways] and !any_h1_to_h9_score_blank and any_h1_to_h9_fairway? and only_nine? ) or ( params[:no_fairways] and !any_h10_to_h18_score_blank and any_h10_to_h18_fairway? and only_nine? ) errors.add_to_base("You inidicated that you missed all the fairways, but you also marked one or more fairways in the scorecard. Either uncheck the fairways mistakenly marked or uncheck the 'No fairways' checkbox.") end if ( params[:no_girs] and any_girs? and !only_nine? ) or ( params[:no_girs] and !any_h1_to_h9_score_blank and any_h1_to_h9_gir? and only_nine? ) or ( params[:no_girs] and !any_h10_to_h18_score_blank and any_h10_to_h18_gir? and only_nine? ) errors.add_to_base("You inidicated that you missed all the greens, but you also marked one or more greens in the scorecard. Either uncheck the marked greens on the scorecard or uncheck the 'No GIRs' checkbox.") end end # attributes_consistency def any_h1_to_h9_score_blank? h1_score.blank? or h2_score.blank? or h3_score.blank? or h4_score.blank? or h5_score.blank? or h6_score.blank? or h7_score.blank? or h8_score.blank? or h9_score.blank? end def any_h10_to_h18_score_blank? h10_score.blank? or h11_score.blank? or h12_score.blank? or h13_score.blank? or h14_score.blank? or h15_score.blank? or h16_score.blank? or h17_score.blank? or h18_score.blank? end def any_h1_to_h9_fairway? h1_fairway? or h2_fairway? or h3_fairway? or h4_fairway? or h5_fairway? or h6_fairway? or h7_fairway? or h8_fairway? or h9_fairway? end def any_h10_to_h18_fairway? h10_fairway? or h11_fairway? or h12_fairway? or h13_fairway? or h14_fairway? or h15_fairway? or h16_fairway? or h17_fairway? or h18_fairway? end def any_h1_to_h9_gir? h1_gir? or h2_gir? or h3_gir? or h4_gir? or h5_gir? or h6_gir? or h7_gir? or h8_gir? or h9_gir? end def any_h10_to_h18_gir? h10_gir? or h11_gir? or h12_gir? or h13_gir? or h14_gir? or h15_gir? or h16_gir? or h17_gir? or h18_gir? end
So how can I access
params
from the model? -
Jay almost 14 yearsThis would be a great solution but could you give an example of how I might implement this? In that particular Railscast the "virtual attributes" are really methods that manipulate real attributes. I have no attributes that
no_fairways
orno_girs
can be associated with. -
Chance almost 14 years@James - the virtual attribute doesn't have to be associated with any database attribute. You could define instance attributes that will work just as well. Updated answer.
-
Scarlet about 6 yearsNote that attr associated with checkbox will not have trythy or falsy value. By default
check_box
generates markup that result in"0"
string when unchecked and"1"
when checked. Even"0".present?
is truthy.