Keep getting: ActiveRecord::UnknownAttributeError in PartiesController#create? - ruby-on-rails

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| %>

Related

Form_tag routing error after unsuccessful submit

I have an index page with a partial form to submit new records to Package model. I keep this form in the index page, so the user doesn't need to leave the page when repeating this action, several times.
In the same page I have a form_tag fir multiple updates for the same controller, namely packages_controller.
Everything works fine, except the following: when hit the update button, going to the form BUT instead of submitting I go back (with the browser) and try to select other records to be updated then I have a routing error:
Routing Error
No route matches [PUT] "/projects/47/orderlines/18/packages"
My index page looks like this:
<% if current_user %>
<%= render "packages/form" %>
<% end %>
<% if #packages.count >= 1 %>
<table class="table table-striped">
<thead>
<tr>
<th> <input type="checkbox" id="selectAll" value="selectAll"></th>
<th>Packed </th>
<th>#No.</th>
<th>Type</th>
<th>Gross weight</th>
<th>Length</th>
<th>Width</th>
<th>Height</th>
<th></th>
<th>Container</th>
</tr>
</thead>
<%= form_tag edit_multiple_project_orderline_packages_path, method: :get do %>
<tbody>
<% for package in #packages %>
<% if package.packed== true %>
<% #label_type="success" %>
<% else %>
<% #label_type="default" %>
<% end %>
<tr>
<td><%= check_box_tag "package_ids[]", package.id %></td>
<td><span class="label label-<%= #label_type %>"><% if package.packed==true %>Packed<% else %>Unpacked<% end %></span></td>
<td><%= package.package_no %></td>
<td><%= package.package_type %></td>
<td><%= package.gross_weight %></td>
<td><%= package.length %></td>
<td><%= package.width %></td>
<td><%= package.height %></td>
<% if #orderline.packages.count >= 1 %>
<td><%= link_to 'Delete', [package.orderline.project, package.orderline, package],
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<td><%= #containers.find(package.container_id).container_id if package.packed %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Add to container", class: "btn btn-primary" %>
<% end %>
<br />
<%= will_paginate %>
<br>
And the multiple_edit form
<div class="col-sm-4">
<%= form_tag update_multiple_project_orderline_packages_path, method: :put do %>
<ul>
<% #packages.each do |package| %>
<li>
<%= hidden_field_tag "package_ids[]", package.id %>
<%= package.package_no %>
<%= package.container_id %>
<% package.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</li>
<% end %>
</ul>
<%= fields_for :package do |f| %>
<div class="field">
<%= f.label :package_no %><br />
<%= f.text_field :package_no, :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :container_id %><br />
<%= select_tag 'package[container_id]', options_from_collection_for_select(#project.containers, 'id', 'container_id', default_blank: true), prompt: "- Select container -", :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :packed %><br />
<%= f.select :packed, [["Packed", true], ["Unpacked", false]],{ prompt: "- Packing -"},{ :class => "form-control" } %>
</div>
<% end %>
<div class="actions">
<br />
<%= submit_tag "Update", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
And the packages controller edit_multiple actions:
def edit_multiple
#project = Project.find(params[:project_id])
#packages = Package.find(params[:package_ids])
end
def update_multiple
#packages = Package.find(params[:package_ids])
#packages.reject! do |package|
package.update_attributes(package_params.reject { |k,v| v.blank? })
end
if #packages.empty?
redirect_to project_orderline_packages_url
else
#package = Package.new(package_params)
render "edit_multiple"
end
end
packages_controller create action:
def create
project = Project.find(params[:project_id])
orderline = project.orderlines.find(params[:orderline_id])
#package = orderline.packages.new(package_params)
#package.save
if #package.save
flash[:success] = "Package(s) was successfully added."
redirect_to :back
else
render 'new'
end
And my routes:
resources :projects do
resources :containers
resources :orderlines do
resources :packages do
collection do
put :packed
get :edit_multiple
put :update_multiple
end
end
end
end
I just added my routes here:
edit_multiple_project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages/edit_multiple(.:format)
packages#edit_multiple
update_multiple_project_orderline_packages_path PUT /projects/:project_id/orderlines/:orderline_id/packages/update_multiple(.:format)
packages#update_multiple
project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#index
POST /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#create
new_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/new(.:format)
packages#new
edit_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id/edit(.:format)
packages#edit
project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#show
PATCH /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
PUT /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
DELETE /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
your form_tag code is update_multiple_project_orderline_packages_path
I think it should be update_multiple_project_orderline_package_path(project_id, orderline_id, package_id)
I am not 100% sure with my statement above, because you gave scrambled Rails Routes, hard to read
and your form action seems goes to packages#edit_multiple controller
so paste your edit_multiple method, not create method
are you implementing your scenario above with javascript, or just plain HTML?

Nested Resource Rails

I have two models namely todo and tasks. Have set up a Has_many, Belongs_to assosciation between them (todo has many tasks, task belongs to todo).
I have set up a nested resource between them as shown below in my routes file
resources :todos do
resources :tasks
end
My form for creating new task is as shown below:
<%= form_for([#todo, #task], html:{class:'form-horizontal'}) do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this todo from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<script type="text/javascript">
$(document).ready(function () {
$('#datep').on('change', function () {
$('.datepicker').hide();
});
});
</script>
<div class="container">
<table style="width:70%" class="table">
<tr>
<td><%= f.label :title , "Task Title"%>
<%= f.text_field :title,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :description,"Task Description"%>
<%= f.text_field :description,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :deadline,"Task DeadLine"%>
<h id="datep"><%= f.text_field :deadline, :class=>'form-control input-sm', "data-provide" => "datepicker" ,"data-date-format" => "mm-dd-yyyy"%></h></td>
</tr>
<tr>
<td><%= f.label :assignee,"Task Assignee" %><br/>
<%= f.collection_select :assignee, User.all, :name, :name, {}, :class => "btn btn-default dropdown-toggle"%></td>
</tr>
<tr>
<td><%= f.label :tags,"Tags for Task"%>
<%= f.text_field :tags,:class=>'form-control input-sm' %></td>
</tr>
<tr>
<td><%= f.label :state,"Task Status"%><br/>
<%= f.select :state, ['Yet To Start', 'In Progress', 'Finished'], {}, :class => "btn btn-default dropdown-toggle"%></td>
</tr>
</table>
</div>
<br />
<div class="actions form-group">
<div class="container">
<%= f.submit 'Create New Task', class:'btn btn-success'%>
<%= link_to todos_path, class: 'btn btn-warning' do %>
<i class="glyphicon glyphicon-hand-left"></i> Back To List
<% end %>
</div>
</div>
<% end %>
My tasks controller code is shown below:
class TasksController < ApplicationController
def new
#task = Task.new
end
def create
#todo = Todo.find.(params[:todo_id])
#task = #todo.tasks.build(task_params)
if #task.save
redirect_to [#todo, #task]
else
redirect_to root_path
end
end
private
def set_todo
#todo = Todo.find(params[:todo_id])
end
def task_params
params.require(:task).permit(:assignee, :deadline, :state, :tags, :title, :description)
end
end
However when i want to add a new task to an particular todo i get this error saying
undefined method `tasks_path' for #<#<Class:0x007fd16a9c8810>:0x007fd169c95a80>
Did you mean? asset_path
Need help to know what am I doing wrong here???
redirect_to only accepts hash, record or string so this line redirect_to [#todo, #task] won't work. See http://api.rubyonrails.org/classes/ActionController/Redirecting.html. You can change it to redirect_to todo_tasks_path(#todo) which is reasonable here.
I also just noticed you didn't put before_filter :set_todo in the controller. You can remove #todo = Todo.find.(params[:todo_id]) in create action as it's no longer needed.
Hope it helps.

Having an issue with strong params during mass assignment

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!

Ruby On Rails Basic Show method failed still

In this block of code, i want to put a button "edit" inside the "show" views. However, due to some reason, it did not works out
My home_controller.rb
class HomeController < ApplicationController
def index
#inputs = Person.all
end
def new
#input = Person.new
end
def create
#input = Person.new(input_params)
respond_to do |x|
if #input.save
x.html {redirect_to :action => 'index'}
else
x.html {render :action => 'new'}
end
end
end
def show
#input = Person.find(params[:id])
end
def edit
#input = Person.find(params[:id])
end
def update
#input = Person.find(params[:id])
respond_to do |x|
if #input.update(input_params)
x.html {redirect_to :action => 'index'}
else
x.html {render :edit}
end
end
end
private
def input_params
params.require(:inputs).permit(:name, :weight, :height, :color, :age)
end
end
My routes file only have two lines:
resources: home
root 'home#index'
My index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th> Weight</th>
<th> Height</th>
<th> Color</th>
<th> Age</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #inputs.each do |person| %>
<tr>
<td><%= person.name %></td>
<td><%= person.weight %></td>
<td><%= person.height %></td>
<td><%= person.color %></td>
<td><%= person.age %></td>
<td><%= link_to 'Show',home_path(person.id) %></td>
<td><%= link_to 'Edit', edit_home_path(person.id) %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Test', new_home_path %>
my show.html.erb:
<p>
<strong>Name:</strong>
<%= #input.name %>
</p>
<p>
<strong>Weight:</strong>
<%= #input.weight %>
</p>
<p>
<strong>Height:</strong>
<%= #input.height %>
</p>
<p>
<strong>Color:</strong>
<%= #input.color %>
</p>
<p>
<strong>Age:</strong>
<%= #input.age %>
</p>
<% link_to 'Edit', edit_home_path(#input) %>
<%= link_to 'Back', home_index_path%>
My form.html.erb
<%= form_for #input, url: {action: "update"} do |person| %>
<div class="field">
<%= person.label :name %><br>
<%= person.text_field :name %>
</div>
<div class="field">
<%= person.label :weight %><br>
<%= person.number_field :weight %>
</div>
<div class="field">
<%= person.label :height %><br>
<%= person.number_field :height %>
</div>
<div class="field">
<%= person.label :color %><br>
<%= person.text_field :color %>
</div>
<div class="field">
<%= person.label :age %><br>
<%= person.number_field :age %>
</div>
<div class="actions">
<%= person.submit %>
</div>
<% end %>
My edit.html.erb
<h1>Editing Data</h1>
<%= render 'form' %>
<%= link_to 'Show', home_path %> |
<%= link_to 'Back', home_index_path %>
The error i get is:
My code <% link_to 'Edit', edit_home_path(#input) %> is point the Edit button to the route home/edit with the obeject #input, that is how i understand it, but it still not working.
Any idea how can i fix this?
Many thanks
The problem is in your show.html.erb. You need to change #person to #input as you have #input defined in your show method

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

Resources