How to post array of objects in rails? - ruby-on-rails

I have the following code in my
new.html.erb
<%= form_tag puppies_path do %>
<% #kennel.each do |puppy| %>
<%= fields_for 'puppies[]', puppy do |p| %>
<div class="field">
<%= p.label :name %><br>
<%= p.text_field :name %>
</div>
<div class="field">
<%= p.label :breed %><br>
<%= p.text_field :breed %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
And puppies[] array variable, which is supposed to post array of objects to controller is posting only single object. Please help to post an array to controller. Thanks in advance!

The usual setup for fields_for is something like this.
<% #kennel.each do |kennel| %>
<%= fields_for :puppies, #kennel.puppies do |p| %>

Yes, I have just found an answer...
In new.html.erb file
<%= form_tag puppies_path do %>
<% 2.times do %>
<%= render 'puppies_group_form' %><br>
<% end %>
<%= submit_tag "Submit" %>
<% end %>
In _puppies_group_form
Name <%= text_field_tag "puppies[][name]" %>
Breed <%= text_field_tag "puppies[][breed]" %>

Related

How to insert new line breaks using form_for with collection_check_boxes

I use the following form_for at one point in my code to display a series of topics for users to select from.
<%= form_for #user do |f| %>
<%= f.collection_check_boxes(:topic_ids, Topic.all.sample(50).each, :id, :topic_name) %>
<%= f.submit %>
<% end %>
When it renders on the page, the boxes are all one-after-the-other. How can I separate them so that there is one check box per line?
from reference here
It is possibly to customize the way the elements will be shown by giving a block to the method as sample below from your code above
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name do |b| %>
<%= b.label(class: "check_box") do %>
<%= b.check_box(class: "check_box") %>
<%= b.object.topic_name %></br>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
You may of course render HTML inside the block:
<%= form_for #user do |f| %>
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, : topic_name do |b| %>
<div class="my-checkbox-wrapper">
<%= b.label(class: "foo") do %>
<%= b.object.topic_name %>
<%= b.check_box(class: "bar") ></br>
<%end%>
<%= f.submit %>
<%end%>
You can have a look at this example
It is very broad question. In short, using CSS.
For example using Bootstrap 4:
<%= form_for #user do |f| %>
<div class="form-check">
<%= f.collection_check_boxes :topic_ids, Topic.all.sample(50).each, :id, :topic_name, class: 'form-check-input' %>
</div>
<%= f.submit %>
<% end %>

Form Refactoring Rails

I am currently creating a form in my rails application but would like some advice on refactoring it. The form is being used to save bagel toppings for an order. The user can select three different toppings (topping1, topping2, and topping3), and the form fields for each one are virtually identical.
ie.
<%= form_for order_item, remote: true do |f| %>
...
<div class="field">
<%= f.label :topping1 do %>
<%= image_tag("http://www.189harwood.com/statics/images/products/ingredients/butter.png", class:"topping") %>
Butter
<% end %>
<%= f.radio_button :topping1, "butter", checked: "checked" %>
</div>
<div class="field">
<%= f.label :topping1 do %>
<%= image_tag("http://www.wpclipart.com/food/dairy/cheese/soft_cream_cheese.png", class:"topping") %>
Cream Cheese
<% end %>
<%= f.radio_button :topping1, "cream cheese" %>
</div>
...
<div class="field">
<%= f.label :topping2 do %>
<%= image_tag("http://www.189harwood.com/statics/images/products/ingredients/butter.png", class:"topping") %>
Butter
<% end %>
<%= f.radio_button :topping2, "butter", checked: "checked" %>
</div>
<div class="field">
<%= f.label :topping2 do %>
<%= image_tag("http://www.wpclipart.com/food/dairy/cheese/soft_cream_cheese.png", class:"topping") %>
Cream Cheese
<% end %>
<%= f.radio_button :topping2, "cream cheese" %>
</div>
...
<%= f.submit "Wrap It Up" %>
<% end %>
Any suggestions on how I can refactor this? Thanks
Try storing the toppings in an array of hashes in your model:
def self.toppings
[{name:'butter', url:'http://www.189harwood.com/statics/images/products/ingredients/butter.png'}, {name:'cream cheese', url:'http://www.wpclipart.com/food/dairy/cheese/soft_cream_cheese.png'}, {...}]
end
In your controller:
my_action
#topping_options = Model.toppings
end
And in your view:
<div class="field">
<% #topping_options.each do |topping| %>
<%= f.label topping[:name].to_sym, topping[:name].humanize %>
<%= image_tag(topping[:url], class:"topping") %>
<%= f.radio_button topping[:name].to_sym %>
<% end %>
</div>

Extend forms without page reload, rails

I'm searching for a solution to extend my form without page reload.
First I tried to render a partial with coffee or javascript, but escape_javascript didnt work.
Here's the view
<%= form_for #recipe = current_user.recipes.build do |f| %>
<%= f.label :name, "Recipe Name" %>
<%= f.text_field :name %>
<%= button_to "Add Ingredient", '#', class: "btn btn-lg btn-primary", id: "add" %>
<p></p>
<%= f.submit class: "btn" %>
<% end %>
The form above should be extented with following partial by every click on the button
<div id="recipe-ingredients">Quantity
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
</div>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
This approach did not work (recipes.js.erb)
$(document).ready(function() {
$("#add").click(function() {
$("p").append("<%= escape_javascript
render(:partial => 'quantities') %>");
});
});
There's a workaround (see below) but I'm searching for a better solution.
$(document).ready(function() {
$("#workout-week").append(<%= escape_javascript(
Haml::Engine.new(File.read(File.join(Rails.root,'app/views',
'_show_period.html.haml'))).render(Object.new, period: #period)) %>);
});
A second approach is to write following lines in Coffee or JavaScript:
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
<% end %>
I'm a newbie so take this with a grain of salt, but have you tried using render :foo instead of redirect_to :foo in the appropriate controller function?
I solved it with cocoon
<%= form_for #recipe do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<div class="links">
<%= link_to_add_association 'add', f, :quantities %>
</div>
</div>
<%= f.submit %>
<% end %>

How to check attribute value of current object in edit form?

I have a nested model. How to check attribute value of object(hotel) of neted model in edit form? I can't figure out how to write if/else statement in _hotels_fields.html.erb
edit.html.erb
<% provide(:title, "Edit trip") %>
<h1>Edit trip</h1>
<%= form_for(#trip) do |f| %>
<%= render 'fields_edit', f: f %>
<%= f.submit "Save changes" %>
<% end %>
_fields_edit.html.erb
<p>
<%= f.label :image %>
<%= f.file_field :image %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p>Hotel</p>
<%= f.fields_for :hotels do |builder| %>
<%= render 'hotels_fields', f: builder %>
<% end %>
_hotels_fields.html.erb
<% if #trip.hotels.name == "hotel" %>
<p>Render any text</p>
<% end %>
<fieldset>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_field :description %>
</p>
</fieldset>
In the context of _hotels_fields.erb.html one specific hotels (why plural here if you have only one?) is represented by f.object. Therefore this should work:
<% if f.object.name == 'hotel' %>
...
<% else %>
...
<% end %>

How to ensure all nested attributes show during 'edit'

I currently have a nested model User has_many Sales_Orders has_many Items.
I can create the Sales_Order with nested Items properly but when I try to 'edit' the Sales_Order, the Sales_Order information is visible but the Items are not shown. Any idea why these wouldn't show?
[sales_orders_controller.rb]
...
def edit
#sales_order = SalesOrder.find(params[:id])
end
[edit.html.erb]
<% provide(:title, "Edit SO") %>
<h1>Edit Sales Order</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#sales_order) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="span3">
<%= f.label :so, "SO#:" %>
<%= f.text_field :so %>
<%= f.label :customer, "Customer:" %>
<%= f.text_field :customer %>
<%= f.label :enter_date, "Date Entered:" %>
<%= f.text_field :enter_date, value: date_formatter(#sales_order.enter_date) %>
<%= f.label :request_date, "Request Date:"%>
<%= f.text_field :request_date, value: date_formatter(#sales_order.request_date) %>
<%= f.label :comments, "CS Comments:" %>
<%= f.text_area :comments %>
</div>
<div class="span3">
<% f.fields_for #sales_order.items do |builder| %>
<%= render 'item_fields', f: builder %>
<% end %>
</div>
<%= f.submit "Save changes", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
[_item_fields.erb]
<fieldset>
<%= f.label :item_code, "Item Code:" %>
<%= f.text_field :item_code %>
<%= f.label :qty_in_kg, "Qty (kg):" %>
<%= f.text_field :qty_in_kg %>
<%= f.label :qc_comments, "Comments:" %>
<%= f.text_field :qc_comments %>
<%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>
<% f.fields_for #sales_order.items do |builder| %>
should be
<%= f.fields_for #sales_order.items do |builder| %>
Without the = you're building the output in the loop but never rendering/printing the return value (the generated HTML output).
Use <%= f.fields_for #sales_order.items do |builder| %>
Notice the = sign. This implies, "evaluate and embed"

Resources