Form Refactoring Rails - ruby-on-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>

Related

How to post array of objects in 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]" %>

Showing multiple iterations of form fields when in edit file of scaffold

First, I have a model called Answers for my trivia game. It stores the multiple possible answers there are to each trivia question (a quiz has_many answers). I created a form via scaffold to make an easy UI for submitting a question with a set of four answers.
I want to do this from one form. When the user currently hits submit, I can post all four answers -- each with a different answer_id but sharing the same question_id (so I can associate 4 answers with one question) -- successfully, like so:
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<div class="field">
<%= f.label :question_text %><br>
<%= f.text_field :question_text, class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="field">
<%= f.label :category_id %><br>
<%= f.number_field :category_id, class: "form-control" %>
</div>
</div>
<h2>Answer Options</h2>
<%= f.fields_for :answers do |answer| %>
<div class="form-group">
<div class="answers">
<div class="field">
<%= answer.label :answer_1 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
</div>
</div>
</div>
<% end %>
<%= f.fields_for :answers do |answer| %>
<div class="form-group">
<div class="answers">
<div class="field">
<%= answer.label :answer_2 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
</div>
</div>
</div>
<% end %>
<%= f.fields_for :answers do |answer| %>
<div class="form-group">
<div class="answers">
<div class="field">
<%= answer.label :answer_3 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
</div>
</div>
</div>
<% end %>
<%= f.fields_for :answers do |answer| %>
<div class="form-group">
<div class="answers">
<div class="field">
<%= answer.label :answer_4 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
</div>
</div>
</div>
<% end %>
If I check in console, it works! I have four different answers (so they are four rows in the table but with the same question_id. What is weird is if I then use the edit route, instead of populating four inputs (like new does), it shows 16 text_field inputs for Answers (labeled Answer 1, Answer 2, Answer 3, Answer 4, Answer 1).
Finally, the other reason I think there could be an issue would be how I am updating the nested Answers attribute through the controller, like so:
def question_params
params.require(:question).permit(:question_text, :category_id, :correct_answer, :answers_attributes => [:id, :answer_text])
end
Am I setting this up incorrectly, such that it would iterate 4x when showing in the Edit file?
I think you need to do little different while rendering the form for edit action:
You can try something like this:
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<% unless #question.new_record? %>
<% #question.answers.each_with_index do |ans,i| %>
<%= f.fields_for :answers, ans do |answer| %>
<%= answer.label "answer_#{i+1}" %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
<% end %>
<% end %>
<% else %>
<h2>Answer Options</h2>
<%= f.fields_for :answers, Answer.new do |answer| %>
<%= answer.label :answer_1 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
<% end %>
<%= f.fields_for :answers,Answer.new do |answer| %>
<%= answer.label :answer_2 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
<% end %>
<%= f.fields_for :answers,Answer.new do |answer| %>
<%= answer.label :answer_3 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
<% end %>
<%= f.fields_for :answers,Answer.new do |answer| %>
<%= answer.label :answer_4 %><br>
<%= answer.text_field :answer_text, class: "form-control" %>
<% end %>
<% end %>
<%= f.submit #question.new_record? ? "Add" : "Update" %>
<% 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"

Rails - Use the same form with new/edit using fields_for

I have 5 models,
Person
person_car
car (has many tires)
person_car_tire
tire (belongs to car)
so I have this view
_form.html.erb
<%= form_for(#person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div>
<% Car.all.each do |c|%>
<div class="field">
<%= f.fields_for(:person_cars) do |ff|%>
Car Name: <%= ff.check_box :car_id %>|<%= c.car_name%>
<% c.tires.each do |b|%>
<div class="field">
<%= ff.fields_for(:person_car_tires) do |fff|%>
Tire: <%#= fff.check_box :tire_id%>|<%= b.tire_name%>
<%end%>
</div>
<%end%>
<%end%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And when I save it works perfectly, the problem comes when I want to edit using this form because it duplicates data of each car 4 times in the view. I've been searching and fields for allows extra options so I made:
<%= form_for(#person) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div>
<% #person.cars.each do |c|%>
<div class="field">
<%= f.fields_for(:person_cars, c) do |ff|%>
Actividad: <%= ff.check_box :car_id %> | <%= c.car.name%>
<% c.person_car_tires.each do |t|%>
<div class="field">
<%= ff.fields_for(:person_car_tires, t) do |fff|%>
Tarea: <%#= fff.check_box :tire_id%>|<%#= t.tire.name%>
<%end%>
</div>
<%end%>
<%end%>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and it now works, but only show the cars and tires that I've selected on the new action. not all as I wanted (because if I use the first form it duplicates checkboxes in the view).
How can I use the same form for both actions?
Hope someone can help me.
You can use the same _form partial for both new and edit. You just need to pass local variables set to different values to this form. Basically, whatever differs, abstract it away as a parameter (local variable) to this function-like partial.

Resources