Having an issue with strong params during mass assignment - ruby-on-rails

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!

Related

Rails 5 ActiveRecord Update Serialized Array in Form

I have a field that is a serialized array. It's loaded into my model and accessed in a form:
class Site < ApplicationRecord
serialize :steps, Array
end
<table class="listing" summary="Site list">
<tr class="header">
<th>Name</th>
<th>Step 1</th>
<th>Step 2</th>
<th>Step 3</th>
<th>Actions</th>
</tr>
<% #sites.each do |site| %>
<tr>
<td><%= site.name %></td>
<% site.steps.each do |step| %>
<td><%= step %></td>
<% end %>
<td class="actions">
<%= link_to("Show", site_path(site), :class => 'action show') %>
<%= link_to("Edit", edit_site_path(site), :class => 'action edit') %>
<%= link_to("Delete", delete_site_path(site), :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
I'm trying to update my edit form so that I can edit each "step" in the array.
<%= form_for(#site) do |f| %>
<table summary="Site form fields">
<tr>
<th>Name</th>
<td><%= f.text_field(:name) %></td>
</tr>
<% a=1 %>
<% #site.steps.each do |step| %>
<tr>
<th>Step <%= a %>
<td><%= text_field :site, :steps, :value => step %></td>
<% a += 1 %>
</tr>
<% end %>
</table>
<div class="form-buttons">
<%= f.submit("Update Site") %>
</div>
<% end %>
The edit form displays the steps field correctly as each individual string in the array. However, when I attempt to submit the form I get the following error:
Attribute was supposed to be a Array, but was a String.
So steps is being submitted as the last entry in the array. How can I display the form correctly and also present the updated array back to the controller for processing?
Your text_field would need to multiple set to true. I believe in your case, something like this should work.
<%= f.text_field(:steps, { multiple: true, value: #site.steps[step] }) %>

undefined method `permit' for nil:NilClass using ruby on rails

Hi im new to ruby on rails. And im exploring the codes on it. Ive got this error line of code
undefined method `permit' for nil:NilClass
here's my controller below
class AddsController < ApplicationController
def new
#add = Add.new
end
def create
#add = Add.new(params[:post].permit(:first_name,:last_name,:email))
if #add.save
redirect_to(:controller=>'home')
else
render 'new'
end
end
end
my new.html.erb
<h1>Add Record </h1>
<%= render 'form' %>
<%= link_to "Back", controller: "home" %>
and my _form.html.erb
<%= form_for #add do |f| %>
<table>
<tr>
<td>FirstName: </td>
<td><%= f.text_field :first_name %></td>
</tr>
<tr>
<td>LastName: </td>
<td><%= f.text_field :last_name %></td>
</tr>
<tr>
<td>Email: </td>
<td><%= f.text_field :email %></td>
</tr>
<tr>
<td> </td>
<td><%= f.submit "Add", :class => 'btn btn-success' %></td>
</tr>
</table>
<% end %>
can someone help me figured out the error?
It should look like:
params.require(:add).permit(:first_name, :last_name, :email)

How to setup the actions with considering database design of rails3

Assume you have the model called 'Topic' as a parent, and 'Comment' as a child.
On the url 'topics/show/35' you can see all the comments that belongs to this topic ID#35.
When logged-in user want to post his new comment at this page,
should I write 'comment_create' action in topics_controller.rb?
or just write 'create' action in comments_controller.rb, and call it from this page?
Which one is regular way??
If I call 'create' action in comments_controller, how can I write in view to pass
'Model name' to add comments into
'Models ID#'
'comment body'
or should I just write actions separately like this?
controllers/comments_controller.rb
def create_in_topic
code here! to add new comment record that belongs to topic....
end
def create_in_user
code here! to add new comment record that belongs to user....
end
for your information, comment adding action should be something like this.
def create
#topic = Topic.find(params[:topics][:id] )
#user_who_commented = current_user
#comment = Comment.build_from( #topic, #user_who_commented.id, params[:topics][:body] )
#comment.save
redirect_to :back
flash[:notice] = "comment added!"
end
Example Updated!!!
views/topics/show.html.erb
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Posted by</th>
<th>Delete</th>
</tr>
<% #topic.comment_threads.each do |comment| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= comment.user.user_profile.nickname if comment.user.user_profile %></td>
<td> **Comment destroy method needed here!!!** </td>
</tr>
<% end %>
</table>
<%=form_for :topics, url: url_for( :controller => :topics, :action => :add_comment ) do |f| %>
<div class="field">
<%= f.label :'comment' %><br />
<%= f.text_field :body %>
</div>
<%= f.hidden_field :id, :value => #topic.id %>
<div class="actions">
<%= f.submit %>
<% end %>
controllers/topics_controller.rb
def add_comment
#topic = Topic.find(params[:topics][:id] )
#user_who_commented = current_user
#comment = Comment.build_from( #topic, #user_who_commented.id, params[:topics][:body] )
#comment.save
redirect_to :back
flash[:notice] = "comment added!"
end
I think the most straight forward implementation it's going to be an action (ie: add_comment) in your Topic Controller. Once the view call the TopicController#add_comment action you will have all your Topic information and also the comment data so you can easily add the comment to the Topic from there.
Let me know if you need further help.
FedeX
Well I'm not to sure because that gem, but you could try something like this:
<%=form_for #topic, url: url_for( :controller => :topics, :action => :add_comment ) do |f| %>
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Posted by</th>
<th>Delete</th>
</tr>
<% #topic.comment_threads.each do |comment| %>
<%= f.fields_for :comment_threads, comment do |comment_form| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= comment.user.user_profile.nickname if comment.user.user_profile %></td>
<td>Delete? <%= comment_form.check_box :_destroy %></td>
</tr>
<% end %>
<% end %>
</table>
<div class="field">
<%= f.label :'comment' %><br />
<%= f.text_field :body %>
</div>
<%= f.hidden_field :id, :value => #topic.id %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Let me know if it helps you! FedeX

Keep getting: ActiveRecord::UnknownAttributeError in PartiesController#create?

I keep getting ActiveRecord::UnknownAttributeError in PartiesController#create:
I have three models: Party, Products, Traits.
class Party < ActiveRecord::Base
has_many :products
accepts_nested_attributes_for :products
end
class Product < ActiveRecord::Base
belongs_to :party
has_many :traits
accepts_nested_attributes_for :traits
end
class Trait < ActiveRecord::Base
belongs_to :product
end
The party form:
<%= form_for(#party) do |f| %>
<% if #party.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#party.errors.count, "error") %> prohibited this party from being
saved:</h2>
<ul>
<% #party.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<table>
<%= f.fields_for :products do |builder| %>
<tr>
<td> <%= builder.label :shirt, "Shirt " %> </td>
<td> <%= builder.text_field :shirt %> </td>
<%= f.fields_for :traits do |builder| %>
<td><%= builder.label :color, "Color" %></td>
<td><%= builder.text_field :color %></td>
<td><%= builder.label :quantity, "Quantity" %></td>
<td><%= builder.number_field :quantity %></td>
</tr>
<tr>
<td><%= builder.label :pants, "Pants " %></td>
<td><%= builder.text_field :pants %></td>
<td><%= builder.label :color, "Color" %></td>
<td><%= builder.text_field :color %></td>
<td><%= builder.label :quantity, "Quantity" %></td>
<td><%= builder.number_field :quantity %></td>
</tr>
<% end %>
<% end %>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The parties controller:
class PartiesController < ApplicationController
def new
#party = Party.new
1.times do
product = #party.products.build
2.times {product.traits.build}
end
end
def create
#party = Party.new(params[:party])
respond_to do |format|
if #party.save
format.html { redirect_to #party, notice: 'Party was successfully created.' }
format.json { render json: #party, status: :created, location: #party }
else
format.html { render action: "new" }
format.json { render json: #party.errors, status: :unprocessable_entity }
end
end
end
The show page:
<%= notice %>
This is <%= #party.name %>'s registry:
<table>
<% for product in #party.products %>
<tr>
<td>Shirt</td>
<td> <%= product.shirt %> </td>
<% for trait in #product.traits %>
<td>Color</td>
<td> <%= trait.color %> </td>
<td>Quantity</td>
<td> <%= trait.quantity %> </td>
</tr>
<tr>
<td>Pants</td>
<td> <%= product.pants %> </td>
<td>Color</td>
<td> <%= trait.color %> </td>
<td>Quantity</td>
<td> <%= trait.quantity %> </td>
</tr>
<% end %>
</table>
<%= link_to 'Edit', edit_party_path(#party) %> |
<%= link_to 'Back', parties_path %>
<% end %>
I've tried everything. What am I missing? Thanks people!
So the params[:party] hash probably contains elements from the form that are not attributes of Party. To debug, try:
def create
#party = Party.new(:name => params[:party][:name])
I think the real complication is that Traits are nested under Products which are nested under Party. This is why the fields_for method for Traits needs to be `builder.fields_for :traits do |traits_fields|' (although I think you could put "builder" instead of "traits_fields".
Then for all of the traits fields, use <%= traits_fields.label :pants, "Pants " %>
Then it should work the way you had it:
def create
#party = Party.new(params[:party])
The error in parameter traits, when it should be "products_attributes"=>{"traits_attributes" => ....
Try this: <%= builder.fields_for :traits do |traits_fields| %> instead of: <%= f.fields_for :traits do |builder| %>

how to display errors notice in Rails?

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

Resources