I have a web app that displays questions with options. The problem is for the options it is displaying whole object along with the body parameter of the object. I do not know what is happening here. Is it something related to serializing and deserializing?
index.html.erb
<tbody>
<% #questions.each do |question| %>
<tr>
<td><%= question.body %></td>
<td><%= question.user.email %></td>
<td>
<%= question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
</td>
<td><%= link_to 'Show', question %></td>
<% if current_user && current_user.admin %>
<td><%= link_to 'Edit', edit_question_path(question) %></td>
<td><%= link_to 'Destroy', question, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<tr>
</tr>
<% end %>
</tbody>
controller_params
private
def set_question
#question = Question.find(params[:id])
end
def question_params
params.require(:question).permit(:body, options_attributes: [:body])
end
model
class Question < ApplicationRecord
belongs_to :user
has_many :options, dependent: :delete_all, :autosave => true
validates_length_of :options, maximum: 4
accepts_nested_attributes_for :options
end
output
<%= question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
Your problem is with this block. Your first part of ERB is telling the view to render question.options.each as well as the followowing HTML, resulting in the objects themselves being rendered. Changing to:
<% question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
Will fix your issue.
Related
I'm trying to update multiple records with one form:
Here's the code in the view:
<%= form_for :product, :url => admin_products_update_multiple_path, :html => { :method => :put } do %>
<table>
<tr>
<th>Supplier Name </th>
<th>Product Name </th>
<th>type_name</th>
<th>brand</th>
<th>image</th>
</tr>
<% #products.each do |product| %>
<%= fields_for "product[]", product do |product_fields| %>
<tr>
<td><%= product.supplier_name %> </td>
<td><%= product.subcategory_name %> </td>
<td><%= product_fields.text_field :type_name %></td>
<td><%= product_fields.text_field :brand %></td>
<td><%= product_fields.text_field :image %></td>
</tr>
<% end %>
<% end %>
</table>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
... and here's the controller action I'm calling to update:
def update_multiple
params['product'].keys.each do |id|
#product = Product.find(id.to_i)
#product.update_attributes(product_params)
end
flash[:notice] = "Update products successfully"
redirect_to(admin_products_path)
end
private
def product_params
params.require(:product).permit(:id, :type_name, :brand, :image)
end
When I run the method, I'm getting a 'Unpermitted parameters' error showing all the ids it's trying to update. Any ideas? Thanks in advance!
Rails newbie here. I'm stuck on fields_for in Rails, and would be eternally grateful for anyone's help.
In Events#new, why am I getting NoMethodError?
Error message says undefined method `name'
In Events, why am I getting NameError?
Error message says undefined local variable or method 'event'.
I am trying to create and view a form where each event has 2 fields for each friend.
_form.html.erb:
<%= form_for(#event) do |f| %>
<div class="field">
Date: <%= f.text_field :date %></br>
Friends: <%= f.fields_for :friends do |friends_fields| %>
<%= friends_fields.text_field :name %>
<% end %>
<% end %>
index.html.erb:
<tbody>
<% #events.each do |event_form| %>
<tr>
<td><%= event_form.date %></td>
<td><%= event_form.friends.each do |friend| %>
<%= friend.name %>
<% end %>
</td>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
event.rb:
class Event < ActiveRecord::Base
has_many :friends
accepts_nested_attributes_for :friends, allow_destroy: true
end
friend.rb:
class Friend < ActiveRecord::Base
belongs_to :event
end
events_controller.rb:
def new
#event = Event.new
2.times { #event.friends.build }
end
Event is not defined because events iterator uses event_form instead of event variable name in each iteration. Try changing to this:
<tbody>
<% #events.each do |event| %>
<tr>
<td><%= event.date %></td>
<td><%= event.friends.each do |friend| %>
<%= friend.name %>
<% end %>
</td>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Hi I have the following code in my model:
class Product < ActiveRecord::Base
before_destroy :check_tasks
has_many :tasks, :order => 'created_at DESC'
validates :name, :presence => true
belongs_to :sprint
validates :sprint_id, :presence => true
def check_tasks
if self.tasks.any?
errors.add_to_base "Product has tasks and cannot be destroyed."
return false
end
end
end
When I am in the product view which lists all the products, I would like to display the error message on the top of the view, every time someone tries to delete a product which has tasks linked to it. I want the message: Product has tasks and cannot be destroyed displayed.
What code should I put in the view below? The view is the product view, which is in the views/products folder.
Thanks!!!
<h1>Listing products</h1>
<%= link_to 'New Product', new_product_path %>
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Sprint</th>
<th></th>
<th></th>
<th></th>
</tr>
<% if not #messages_rendered -%>
<% if flash[:error] -%>
<p class='error'><%=h flash[:error] %></p>
<% end -%>
<% if flash[:notice] -%>
<p class='notice'><%=h flash[:notice] %></p>
<% end -%>
<% end -%>
<% #messages_rendered = true -%>
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.description %></td>
<td><%= product.sprint.name %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
Try putting this in your product_controller:
def destroy
...
flash[:error] = #product.errors.full_messages.join(' ')
...
end
How could you do what's covered in RyanB's Railscast on editing multiple records individually, using Formtastic? Formtastic doesn't use form_tag, which RyanB's method relies on.
The semantic_form_for is just a wrapper around form_for so you can use the same parameters. Here is a formtastic version of Ryan Bates' screencast
views/products/edit_individual.html.erb
<% semantic_form_for :update_individual_products, :url => update_individual_products_path, :method => :put do |f| %>
<% for product in #products %>
<% f.fields_for "products[]", product do |ff| %>
<h2><%=h product.name %></h2>
<%= render "fields", :f => ff %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
views/products/index.html.erb
<% semantic_form_for :edit_individual_products, :url => edit_individual_products_path do %>
<table>
<tr>
<th></th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
</tr>
<% for product in #products %>
<tr>
<td><%= check_box_tag "product_ids[]", product.id %></td>
<td><%=h product.name %></td>
<td><%=h product.category.name %></td>
<td><%= number_to_currency product.price %></td>
<td><%= link_to "Edit", edit_product_path(product) %></td>
<td><%= link_to "Destroy", product, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<p>
<%= select_tag :field, options_for_select([["All Fields", ""], ["Name", "name"], ["Price", "price"], ["Category", "category_id"], ["Discontinued", "discontinued"]]) %>
<%= submit_tag "Edit Checked" %>
</p>
<% end %>
Please note that you can use the form_for helpers as well in formtastic.
Update
If you like to use nested attributes as well it should work out of the box, using fields_for on the form partial. Lets stick with the railscast example and say that:
product.rb
has_many :commments
accepts_nested_attributes_for :comments
You can edit the comments on the _fields.html.erb of the products like:
<%= f.fields_for :comments do |cf| %>
<%=render 'comments/fields', :f=>cf%>
<%end%>
And make sure you have a fields partial in your comments views.
I'm attempting to use the fields_for command to combine two models edit functions. I'm editing several variables. With these variables I'd like to include some basic information that is associated with the model, such as #line_item.inventory.item. The only way I could accomplish this is by creating a double loop which doesn't work for obvious reasons. Is there a way to pass two arguments into a for loop?
ie. fields_for :line_items & #order.line_items do ???
<% f.fields_for :line_items do |f| %>
<% for line_item in #order.line_items do %>
<td><%= line_item.inventory.item %></td>
<td><%= f.text_field :inventory_id, :size => 3 %></td>
<td><%= line_item.inventory.unit2_id %></td>
<td><%= line_item.inventory.catalognumber %></td>
<td><%= f.text_field :quantity, :size => 3 %></td>
<td> <%= f.text_field :item_price, :size => 3 %></td>
<td><%= f.text_field :total_price, :size => 3 %></td>
<td><%= f.check_box :received %><b>Received</b> </td>
<td><%= f.text_field :notes %></td>
<td><%= link_to 'remove item', line_item, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
<% end %>
You should look at accepts_nested_attributes_for. When used correctly, it can solve your problem.
Assuming the encompassing form is for an order you want to add the following to the Order model, if it isn't already there.
class Order < ActiveRecord::Base
has_many :line_items
accepts_nested_attributes_for :line_items
end
And the view:
<% form_for :order do |f| %>
...
Order specific fields
...
<% f.fields_for :line_items do |line_item_form| %>
<% line_item = line_item_form.object
<td><%= line_item.inventory.item %></td>
<td><%= line_item_form.text_field :inventory_id, :size => 3 %></td>
<td><%= line_item.inventory.unit2_id %></td>
<td><%= line_item.inventory.catalognumber %></td>
<td><%= line_item_form.text_field :quantity, :size => 3 %></td>
<td> <%= line_item_form.text_field :item_price, :size => 3 %></td>
<td><%= line_item_form.text_field :total_price, :size => 3 %></td>
<td><%= line_item_form.check_box :received %><b>Received</b> </td>
<td><%= line_item_form.text_field :notes %></td>
<td><%= link_to 'remove item', line_item, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
fields_for, when used with accepts_nested_attributes_for and given an association, will loop through all items already associated with the object of the parent form builder. In all other cases fields_for does not use a loop.
First of all, if you need to do nested models I recommend you to view these three railscasts innmediately.
In your case I would start by interchanging the "for" and the "fields for":
<% for line_item in #order.line_items do %>
<% f.fields_for :line_item do |f| %>
... (snip)
<% end %>
<% end %>
Then I would realize that a I could move the entire fields_for to a partial view and use a render call with a :collection parameter:
in order.html.erb:
<%= render :partial => :line_item, :collection => order.line_items %>
in _line_item.html.erb:
<% f.fields_for :line_item do |f| %>
... etc
Now you don't have any "for". :)
Also, your "line items" are inside an "#order" object, so I imagine there's a form_for somewhere up:
<% form_for #order ... %>
...
<%= render :partial => :line_item, :collection => order.line_items %>
...
<% end %>
Now you have your views fixed. But you still have to make your Orders model "handle" its children correctly.
I'm not sure there is really a way for this, since the fields_for block and the for loop are basically 2 different things. So it's not really a "double loop".