I created a form ("Form1") and a validation to go along with it. Then I created a different form ("Form2") for another purpose but the validation method for "Form1" is being triggered when I submit Form2
Form2 and Form1 are both being submitted to the same database, but I didn't think the validation would apply to both of them, because attribute/method names were different in the forms
Form 1
<%= form_for(#guess) do |f| %>
<% if #guess.errors.any? %>
<div class="field">
<%= f.label(:math, "I think many students will fail Math") %>
<%= f.check_box(:math) %> </br>
</div>
<div class="field">
<%= f.label(:french, "I think many students will fail French") %>
<%= f.check_box(:french) %> </br>
</div>
I do the same for 6 subjects. Students are required to select 3 subjects that might create fails..
Validation for Form1 in model Guess.rb
validates_inclusion_of :possible_assessment_failures, :in => 1..3, :message => "You must check off 1,2 or 3 different assessments for question 1"
...
def possible_assessment_failures
[math, french, english, science, history, geography].select{|x| x }.count
end
Comment: I assumed that this validation got triggered because the methods in the form (:french, :math etc) were in the array [math, french...] in the validation...I'm guessing that's wrong
--
Form2
In the controller....
#teacher = Guess.new
in the view...
<div class="field">
<%= f.label(:MrSmith, "MrSmith") %>
<%= f.select:MrSmith, 1..6 %> </br>
</div>
So why is the validation for form1 getting called when I submit form2?
As mentioned, I thought the validation got called for form1 because the methods in the array in the validation (i.e. the names of the subjects
[math, french, english, science, history, geography].select{|x| x }.count
were named in the form
<%= f.check_box(:math) %>
so if my Form2 has different attributes (like teacher's names
<%= f.select:MrSmith, 1..6 %>
I don't understand why that would trigger a validation with the names of subjects (math, french etc) in it?
I'm assuming that's totally wrong thinking on my part. So what triggers the validation and how do I get it not to apply on form2?
All of the validations in Guess.rb are called whenever the guess model is saved (by default, you can disable them with save(:validate => false)).
It's not generally a good idea to only apply some validations when saving a model since you'll lose the guarantee that your database is consistent with all of your validations.
If you really want to do it, you could create a new attribute and only run the validation if that attribute is true, see this answer https://stackoverflow.com/a/3956701/625365
Related
I'm using the cocoon gem in a Rails4 app to create a nested form
dynamically. Each Lease object my have zero or more MonthlyCharge
objects associated with it. (I.e., the Lease model has_many
:monthly_charges, and the MonthlyCharge model belongs_to :lease.)
I have a form for leases in app/views/leases/_form.html.erb that
calls monthly charges:
<h3>Monthly Charges</h3>
<div id="monthly_charges">
<%= f.fields_for :monthly_charges do |monthly_charge| %>
<%= render 'monthly_charge_fields', :f => monthly_charge %>
<% end %>
<div class="links">
<%= link_to_add_association "Add a Monthly Charge", f, :monthly_charges %>
</div>
</div>
But when I click on "Add a Monthly Charge", three sets of form fields
appear, rather than one.
On top of that, no matter if I fill out the form for one monthly
charge or not, and regardless of whether I click on "Remove Charge"
for the others, rails doesn't save the monthly charge.
Gist is
here.
What can I possibly be doing wrong? It was suggested that I might be
calling the cocoon js file more than once, but I've searched through
the source tree and haven't found any but a single reference to it, in
app/assets/javascripts/application.js. Any input appreciated. Thanks.
After the user submits the form, but before the association is added, is it possible to modify the nested field during this time?
For example my nested fields may look like:
<div class='nested-fields'>
<div class="field">
<%= f.label :count %>
<%= f.number_field :count %>
</div>
<%= link_to_remove_association "remove section", f %>
</div>
Say I want to multiply count x 2 before adding the association (after user submits form). Is this possible?
Or a more complex example, I might want to convert the integer to a string then save the association.
link to issue: https://github.com/nathanvda/cocoon/issues/361 (i was told to post on SO)
Yes, you can modify you permit params:
def some_params
params.require(:some).permit(:count).tap do |white_list|
white_list[:count] = 2 * params[:some][:count].to_i
end
end
I have a rails model that has two field attributes: :commission_fixed & :commission_percentage. The user should only be able to choose between one of the two options either: :commission_fixed or :commission_percentage not both on form submit. Is this possible using Rails validation? If so what is the best way to achieve this?
Your problem is within the way you've structured your column names / model attributes.
Ideally you should change your attribute names on your model to :commission_method and :commission_rate. This allows for greater flexibility. Then in your view you can achieve what you're looking for with a radio button. You can store your :commission_rate as a decimal in the db.
<%= f.radio_button :commission_method, "Fixed" %>
<%= f.radio_button :commission_method, "Percentage" %>
<%= f.number_field :commission_rate %>
In your view files if you need to switch between showing a fixed amount and a percentage you can just do:
<% case #sales_associate.commission_method %>
<% when 'Fixed' %>
<span>Fixed: <%= number_to_currency(#sales_associate.commission_rate) %></span>
<% when 'Percentage' %>
<span>Percentage: <%= "% #{#sales_associate.commission_rate}" %></span>
<% end %>
However, you "could" write a custom validation method that throws an error if both attributes were assigned.
In whatever model:
class SalesAssociate
validate :only_one_selected_commission
def only_one_selected_commission
errors[:base] << "Please select only one form of commission" if self.commission_fixed.present? && self.commission_percentage.present?
end
end
I'm new to rails and getting stuck on best practice for complex forms.
I have 3 layers deep nested attribute forms. User > Recipient > Gift_profile.
I want to create a single partial for _gift_profile_fields so I can use the fields in multiple forms around the site and not repeat myself. They are located at different levels of the hierarchy.
It works fine until I add the check_box_tag where I manually specify the name for a HABTM relationship with another model called Sport, which has_and_belongs_to_many gift profiles.
<%= f.label :gender, "Gender" %>
<%= f.select :gender, options_for_select(GiftProfile::GENDERS), :include_blank => true %>
<% for sport in Sport.find(:all) %>
<div>
<%= check_box_tag "recipient[gift_profile_attributes][sport_ids][]", sport.id, #gift_profile.sports.include?(sport) %>
<%= sport.sport %>
</div>
The form works perfectly, but obviously only works on the recipient form. It fails to work on other form locations where I assume I would need:
"user[recipient_attributes][gift_profile_attributes][sport_ids][]"
Is there a helper or way to dynamically update this so that I can continue to use the partial on all my forms? Is check_box_tag the best way to do this or is there another rails helper?
A friend suggested I use a helper to generate the name depending on the controller.
Have a page where there are multiple input fields of the same thing, Posts. Right now, when a user enters in a question for, let's say 3 fields, the only one that saves to the database is the last one. Whereas, it should save all three and give them each it's own post_id. Also; if the user doesn't enter anything in for the other fields, it should not save in the database either.
<%= form_for(#post) do |f| %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<% end %>
It's failing because what you've got above evaluates to thee html field with the same name/id and the browser will only post the value for one of them. If they are different fields, then you need to give them unique names/ids or you need to create them as an array eg:
<%= f.text_field_tag 'content_array[]' %>
or, if you want these to be a set of posts - you'll need to add multiple sub-forms (one for each post) using a custom form.
What you can do is convert to html and as an array
in your form:
<input`type="text" name="post[content][]" id="content_id">
Then, in your controller:
content_details = params[:post][:content]
content_details.each do|cont|
#post = Post.new(content: cont)
#post.save
This will loop through all of the content created and save each.