Checkboxes in single form for multiple objects - ruby-on-rails

In trying to create a single form to add multiple objects, I followed this tutorial and got it working. Problem is, I can only enter values for string attributes and not for boolean attributes as it messes the params up. Where is my form going wrong?
http://vicfriedman.github.io/blog/2015/07/18/create-multiple-objects-from-single-form-in-rails/
<%= form_tag boa_constrictors_litter_hash_path do %>
<% #litter.each do |snake| %>
<%= fields_for 'offspring[]', snake do |f| %>
<%= f.hidden_field :type, :value => "BoaConstrictor" %>
<%= f.text_field :name, placeholder: "Name"%>
<%= f.label :gender %>
<%=f.select :gender, options_for_select([['Male', 'Male'],
['Female', 'Female']]) %>
<%= f.hidden_field :year, :value => "2017" %>
<%= f.label :available %>
<%= f.check_box :available %>
<%= f.label :private %>
<%= f.check_box :private %>
<%= f.label "Notes" %>
<%= f.text_field :notes %>
<% if #dame.hypo? or #sire.hypo? %>
<%= f.label "Hypo" %>
<%= f.check_box :hypo %>
<% end %>
<% if #dame.img? or #sire.img? %>
<%= f.label "IMG" %>
<%= f.check_box :img %>
<% end %>
<% end %><br>
<% end %>
<%= submit_tag %>
Ex; Creating two snakes, one named "first" w/ available: true and the other named "second" sends the following params which creates three snakes with incorrect attributes:
"offspring"=>[{"type"=>"BoaConstrictor", "name"=>"first", "gender"=>"Male",
"year"=>"2017", "available"=>"0"}, {"available"=>"1", "private"=>"0",
"notes"=>"", "hypo"=>"0", "img"=>"0", "type"=>"BoaConstrictor",
"name"=>"second", "gender"=>"Male", "year"=>"2017"}, {"available"=>"0",
"private"=>"0", "notes"=>"", "hypo"=>"0", "img"=>"0"}], "commit"=>"Save
changes"}
If I entered two animals, one named "first" with notes "works" and the other named "second " with notes "now", it gives the correct params and creates two animals correctly.
"offspring"=>[{"type"=>"BoaConstrictor", "name"=>"first", "gender"=>"Male",
"year"=>"2017", "available"=>"0", "private"=>"0", "notes"=>"works",
"hypo"=>"0"}, {"type"=>"BoaConstrictor", "name"=>"second", "gender"=>"Male",
"year"=>"2017", "available"=>"0", "private"=>"0", "notes"=>"now",
"hypo"=>"0"}], "commit"=>"Save changes"}
If I check any of the booleans in the form, the params chop at that attribute and repeat leading to extraneous objects and messing up the attributes of any of the objects that follow.
Solved
Check_box does not work correctly for attributes within an array as documented here: https://apidock.com/rails/ActionView/Helpers/FormHelper/check_box
Solution was to use check_box_tag
Instead of <%= f.check_box :private %>, using <%= check_box_tag 'offspring[][private]' %> works fine.

check_box does not work correctly for attributes within an array as documented here.
Solution was to use check_box_tag:
Instead of <%= f.check_box :private %>,
using <%= check_box_tag 'offspring[][private]' %> works fine.

Related

Passing information to a controller through params (not saving it to the db). How to put it inside a hash like the users params hash

I have information that is passed to a controller method but isn't saved to the DB. I want to access this information, that is passed to the controller method as a whole hash, but it is all individual data as you will see below.
Here is the params:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0O7pbNNrddHCyPL9B/avUUD85574rFBfS57h+aWKK/mBakPSn5iHJKHhPmvuJVfyWxjBsAQn2kagwkTOALEKRg==", "page"=>{"content_top"=>"", "content_bottom"=>""}, "header1"=>"iijijij", "column1"=>"ijijijij", "header2"=>"", "column2"=>"", "header3"=>"", "column3"=>"", "header4"=>"", "column4"=>"", "commit"=>"Save", "guide_id"=>"dungeon-boss", "category_id"=>"heroes", "id"=>"link-skill"}
As you can see there is a page hash and after, it is header1 column1 header2 column2... and so on. With the header1 info, I'm trying to put it inside a params hash like the page hash has for the values passed in it. So it's like "table" =>{"header1"=>"iijijij", "column1"=>"ijijijij", "header2"=>"", "column2"=>"", "header3"=>"", "column3"=>"", "header4"=>"", "column4"=>""}
I'm sure there is something I need to add to the form so it know to group them like this. Here is the form I currently have
<% if (current_user.mod_of_game?(#guide) unless current_user.nil?) %>
<%= form_for([#category, #page], url: update_pages_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :content_top, "Top Content" %>
<%= f.text_area :content_top, :class => 'editor' %>
<%= f.label :content_bottom, "Bottom Content" %>
<%= f.text_area :content_bottom, :class => 'editor' %>
<!-- to be in one hash when passed -->
<%= text_field_tag :header1 %>
<%= text_field_tag :column1 %>
<%= text_field_tag :header2 %>
<%= text_field_tag :column2 %>
<%= text_field_tag :header3 %>
<%= text_field_tag :column3 %>
<%= text_field_tag :header4 %>
<%= text_field_tag :column4 %>
<!-- end -->
<%= f.submit "Save" %>
<% end %>
I cant find what I need to add to make the text_field_tag data all be in one hash when passed.(the text_field_tag is purposely not being saved to the DB on form submit, it just needs to be passed to the method and grouped inside a hash)
how about using fields_for like this
<%= form_for([#category, #page], url: update_pages_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :content_top, "Top Content" %>
<%= f.text_area :content_top, :class => 'editor' %>
<%= f.label :content_bottom, "Bottom Content" %>
<%= f.text_area :content_bottom, :class => 'editor' %>
<!-- to be in one hash when passed -->
<%= f.fields_for :table do |t| %>
<%= t.text_field_tag :header1 %>
<%= t.text_field_tag :column1 %>
<%= t.text_field_tag :header2 %>
<%= t.text_field_tag :column2 %>
<%= t.text_field_tag :header3 %>
<%= t.text_field_tag :column3 %>
<%= t.text_field_tag :header4 %>
<%= t.text_field_tag :column4 %>
<% end %>
<!-- end -->
<%= f.submit "Save" %>
<% end %>
You can simply use the array way if you want to send the data that doesn't belong to the model, in params hash inside page key. Here's how:
<%= text_field_tag 'page[header1]' %>
Not only this, if you would like to use another key, you can use that as well like <%= text_field_tag 'custom_key[header1]' %>

How to add custom validation error message adjacent to input fields in Rails 3?

My Code in View Page(views/session/new.html.erb) :
< %= form_for(:session, :url => sessions_path) do |f| %>
<%= f.label :email, 'Username'%>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit 'Login'%>
<%= link_to 'Forgot Your Password?', new_password_reset_path >
< % end %>
I have written proper validation codes in my model file.
But I want that on Submit, the validation errors should pop up at the adjacent to the fields rather than at the top of the Page.
Thanks in Advance !
If you're inclined to use Rails' built-in server side validations, you can check for whether validation errors exist, then print them if they do:
<%= form_for(:session, :url => sessions_path) do |f| %>
<%= f.label :email, 'Username'%>
<%= f.text_field :email %>
<% if f.object.errors[:email] %>
<%= f.object.errors[:email].join(", ") %>
<% end %>
<%= f.label :password %>
<%= f.password_field :password %>
<% if f.object.errors[:password] %>
<%= f.object.errors[:password].join(", ") %>
<% end %>
<%= f.submit 'Login'%>
<%= link_to 'Forgot Your Password?', new_password_reset_path >
<% end %>
Note a few things:
First, because you're passing a symbol, rather than an object in your form, you'll need to access the object's attributes from within the form_for block by invoking f.object.
Second, because some fields may yield more than one validation error, you'll want to print them out in sequence. Using Ruby's join method can help you concatenate these in a coherent manner.
UPDATE:
If you want the errors to render directly beside the corresponding text field, you'll need to apply some CSS. Clearly, it's recommended that a stylesheet be used to for this, but in the interest of simplicity, here's of an example of how this might be rendered using inline styling:
<%= f.text_field :email, :address, :style => "display: inline-block; float: left;" %>
<% if f.object.errors[:email] %>
<span style="display: inline-block; float: left;">
<%= f.object.errors[:email].join(", ") %>
</span>
<% end %>
<div style="clear: left;"></div>
I'd go with something like this:
<%= form_for(:session, :url => sessions_path) do |f| %>
<%= f.label :email, 'Username' %>
<%= f.text_field :email %>
<%= f.object.errors[:email].to_sentence if f.object.errors[:email] %>
<% end %>
I reckon you'll figure out the rest.
You can access the values of error messages of different model attributes with errors hash like errors[:some_attribute_name]. As long as your custom validators store error message in the right model attribute, you can probably do something like this.
< %= form_for(:session, :url => sessions_path) do |f| %>
<%= f.label :email, 'Username'%>
<%= f.text_field :email %>
<%= f.object.errors[:email] %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.object.errors[:password] %>
<%= f.submit 'Login'%>
<%= link_to 'Forgot Your Password?', new_password_reset_path >
< % end %>
I'll let you worry about how the error is displayed beside the form and stuff. :)

Using placeholder in a update form

I want to replace the default value of a text_field in a update form by a placeholder. How can I do that ?
My first thought was the following code but the default value of the text_field is still here :
<%= form_for(some) do |f| %>
<div><%= f.text_field :thing, placeholder: "what an example !" %></div>
<%= f.submit %>
<% end %>
You can use text_field_tag
<%= form_for(some) do |f| %>
<div>
<%= text_field_tag "some_thing", (some.thing unless some.thing=="default value"), :name=> "some[thing]", :placeholder => "what an example !" %>
</div>
<%= f.submit %>
<% end %>
Hope, it will work..
Thanks

Rails: loop through array to create output

I have a model "tube" which is a database having the various data for vacuum tubes. I want to dynamically loop through all the columns and create a basic table for my "new" and "edit" pages.
I grab the attribute names like this:
<% attr_array = #tube.attribute_names %>
And I want to do something like this:
<% attr_array.each{|x| text_field :x } %>
in hopes of dynamically generating this:
<%= form_for #tube do |f| %>
<%= f.label :name, :class=>'std_label' %>:
<%= f.text_field :name, :class=>'std_input' %>
<%= f.label :functional_class, :class=>'std_label' %>:
<%= f.text_field :functional_class, :class=>'std_input' %>
<%= f.label :base_type, :class=>'std_label' %>:
<%= f.text_field :base_type, :class=>'std_input' %>
.... and so forth ....
<%= f.submit %> <% end %>
But of course this does not work, not by a long shot. How can I generate my text_field inputs dynamically based on the attribute_names array? The table I am using has about 30 attributes and I think it's silly to build them all by hand, especially given that if they change in the future then the code will break. Googling and reading the API have given me the lectures on why this doesn't work, but has left me hi and dry with a code example of what does.
Accurate help appreciated.
What about:
<%= form_for #tube do |f| %>
<% #tube.attribute_names.each do |attr| %>
<%= f.text_field attr, :class=>'std_input' %>
<%= f.label attr, :class=>'std_label' %>:
<% end %>
<%= f.submit %>
<% end %>

Problem accessing variable in a nested form partial

I have a nested form in a rails view that is called like this
<% f.fields_for :invoice_item_numbers do |item_no_form| %>
<%= render 'invoice_item_number', :f => item_no_form %>
<% end %>
and the partial (_invoice_item_number.html.erb) looks like this
<div class='invoice_item_numbers'>
<% if f.object.new_record? %>
<li><%= f.label :item_number %><%= f.text_field :item_number %>
<%= link_to_function "remove", "$(this).parent().remove()", :class => 'remove_link' %></li>
<% else %>
<li class="inline"><%= f.label :item_number %><%= f.text_field :item_number %>
</li><li class="inline"><%= f.label :description %><%= invoice_item_number.description %></li><li><%= f.label :amount %><%= f.text_field :amount %>
<%= f.check_box '_destroy', :class => 'remove_checkbox' %>
<%= f.label '_destroy', 'remove', :class => 'remove_label' %></li>
<% end %>
</div>
This fails with the error message
undefined method `description' for nil:NilClass
Why does invoice_item_number return a nil object in this partial? It is obviously being defined somehow because if I change it to something else (e.g. item_number.description then the error message becomes undefined local variable or methoditem_number' for #instead. The invoice_item_number object that is being displayed by this partial is being used perfectly well by the form helpers as<%= f.text_field :item_number %>and<% f.text_field :amount %>both work perfectly well. I have tried a number of solutions such as using#invoice_item_number` and explicitly defining an object in the render method but these have not worked.
Presumably there is a very simple answer to this.
Just re-read the Ryan's scraps post on nested forms at http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes and found the answer. It was sort of in my code already but I didn't understand what was happening. I can access the invoice_item_number object with f.object so replacing <%= invoice_item_number.description %> with <%= f.object.description %> solved my problem.
how about changing:
<%= invoice_item_number.description %>
to
<%= f.label :description %>
or if you need a field:
<%= f.text_field :description %>

Resources