Create multiple entries with checkbox and strong params in Rails4 - ruby-on-rails

I am having problems with the following scenario:
My users do searches by keywords which produces a list. The user has 2 actions either add them to a favorites table or block them using check boxes.
The problem I have is that when users click "Add to Favorites" the form passes a list of hashes to my strong params method and I am not able to pass it correctly.
I think the problem is that the hash required by strong_params is inside another hash.
Also I have no idea on how to pass the same hash to the BlockController when user click "Block"
This is the error message:
param is missing or the value is empty: {:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}
My results.html.erb is
<table class="table table-striped table-bordered">
<tr>
<th class="center">Name</th>
<th class="center">Title</th>
<th class="center">Company</th>
<th class="center">Location</th>
<th class="center">Profile</th>
<th class="center">Select</th>
</tr>
<%= form_tag favorites_path do %>
<%= #results.length %>
<% #results.each do |key,value| %>
<tr>
<td><%= value['name'] %></td>
<td><%= value['title'] %></td>
<td><%= value['company'] %></td>
<td><%= value['location'] %></td>
<td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
<td><%=check_box_tag 'favorite[]', {:name => value['name'],:title =>value['title'],:company => value['company'],:location => value['location'], :profile=> value['profile'], :notes =>""}%></td>
</tr>
<% end %>
<%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
<%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
<% end %>
</table>
this is how my strong_params method looks:
def favorite_params
params[:profiles].each do |e|
params.require(e).permit(:name, :title, :company, :location, :profile, :notes)
end
end
Any ideas?
Update:
I am able to pass params as:
def favorite_params
params.permit(:commit,favorite:[])
end
create method:
def create
#favorite = Favorite.new(favorite_params)
#favorite.user_id = current_user.id
respond_to do |format|
if #favorite.save
format.html { redirect_to #favorite, notice: 'Favorite was successfully created.' }
format.json { render :show, status: :created, location: #favorite }
format.js { render :show, status: :created, location: #favorite }
else
format.html { render :new }
format.json { render json: #favorite.errors, status: :unprocessable_entity }
end
end
end

Reference to http://api.rubyonrails.org/classes/ActionController/Parameters.html
Don't use each, use permit or require directly
Try this:
params.permit(profiles: {favorites: [:name, :title, :company, :location, :profile, :notes]})
#or :
params.permit(profiles: [{favorites: [:name, :title, :company, :location, :profile, :notes]}])
#=>{:profiles=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}}
or :
params.require(:profiles).permit( favorites: [:name, :title, :company, :location, :profile, :notes])
#=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}
UPDATE
According to OP's modification of the view, the favorite_params should be:
params.require(:favorite)
Then in the create action use each to create every member of the array, becase check_box pass string as value, we have to eval the string into hash again.
favorite_params.each do |fp|
f=Favorite.new(eval(fp))
f.user_id = current_user.id
f.save
end
But use eval to transfer the params is not safe. I suggest you to modify your view to:
<%= form_tag favorites_path do %>
<%= #results.length %>
<% #results.each do |key,value| %>
<tr>
<td><%= value['name'] %></td>
<td><%= value['title'] %></td>
<td><%= value['company'] %></td>
<td><%= value['location'] %></td>
<td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
<td><%= check_box_tag "favorites[#{value['name']}][checked]", 'checked',true %>
<%= hidden_field_tag "favorites[#{value['name']}][name]" , value['name'] %>
<%= hidden_field_tag "favorites[#{value['name']}][title]" , value['title'] %>
<%= hidden_field_tag "favorites[#{value['name']}][company]" , value['company'] %>
<%= hidden_field_tag "favorites[#{value['name']}][location]" , value['location'] %>
<%= hidden_field_tag "favorites[#{value['name']}][profile]" , value['profile'] %>
<%= hidden_field_tag "favorites[#{value['name']}][note]" , "" %>
</td>
</tr>
<% end %>
<%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
<%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
<% end %>
From this view, you may have params like this:
{:favorites=>{
"Jon Doe" => {:checked => "checked", :name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""},
"Alberto" => {:name=>"Alberto", :title=>"DS", :company=>"Dufrain", :location=>"chester", :profile=>"", :notes=>""}
}
}
Then change your favorite_params to :
params.require(:favorites).select{|k,v| v[:checked]}.map{|k,v| v.except(:checked)}
Use select to get all checked members, and except the checked hash key that generated by check_box,so you could get an array of hashes like:
[{"name"=>"Jon Doe", "title"=>"Provider", "company"=>"Acme", "location"=>"Dubai", "profile"=>"Group A", "notes"=>""}]
Then you could use favorite_params safely without eval.
But on my point, your requiement is so similar as Mark V's question. So you can study using accepts_nested_attributes_for to simplify your code.

i am on the way home so have to use my phone to type a new answer. my spell may wrong.
as you see in your console. you should get the favorites array use require only.
params.require(:favorite)
then in your create action use each to create every member of the array.
favorite_params.each do |fp|
f=Favorite.new(fp)
f.user_id =
f.save
end

Related

pass array hidden field in nested model rails

I have following code in my view:
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= f.hidden_field :modul1_id, id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<%end%>
params passing in console
Parameters: {"authenticity_token"=>"LJ/ZME2lHZ7VwCDgPKX6OFe326fXSXo5UB4M0cPwbCE=", "esthour"=>{"rfp_id"=>"6", "ecommerce_est_hours"=>"", "modul1hours"=>{"module_est_hours"=>"3"}, "designpages_est_hours"=>"", "cms_est_hours"=>""}, "modul1_ids"=>["12", "13", "14"], "utf8"=>"✓", "project_id"=>"second", "commit"=>"Add Todo"}
Current user: admin (id=1)
modul1_ids is the hidden array based on that three text box is created but when i submit the page gives me:
ActionView::Template::Error (undefined method `merge' for 12:Fixnum):
in first textbox i passed 1
second 2
and in third 3
last value(3) isthe s passing that one can see in the console params module_est_hours"=>"3, but what about rest two fields y not passing and whats the solution for an error. Please help me.
Edit 1
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= hidden_field_tag "modul1_ids[]", id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<%end%>
this code does not give the error, but also value is not stored in modul1hours table
The field of the modul1hours table are:
integer :modul1_id
decimal :module_est_hours
decimal :module_act_hours
integer :esthours_id
]
.rb
belongs_to :esthour
attr_accessible :module_est_hours,:module_act_hours
and controller
Update
def new
#esthour = Esthour.new
#gg = #esthour.modul1hours.build
#project = params[:project_id]
#rfp = params[:rfp_id]
#m1 = Modul1.where(:rfp_id => #rfp.id)
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #esthour }
end
end
over Update
# GET /project_todos/1/edit
def edit
#esthour = Esthour.find(params[:id])
end
def create
#project = params[:project_id]
#esthour = Esthour.new(params[:esthour])
user_params = params.select{|k,v| k.include?('esthour')}
respond_to do |format|
if #esthour.save
get_issue_attribute_param1(user_params)
format.html { redirect_to project_rfp_url(#project,#esthour.rfp_id), :notice => 'hours was successfully created.' }
format.json { render :json => #esthour, :status => :created, :location => #esthour }
else
format.html { render :action => "new" }
format.json { render :json => #esthour.errors, :status => :unprocessable_entity }
end
end
end
is there any build needed?eg Esthour.modul1hour.build in new def of controller coz record not saved in table?
view
<%= form_for #esthour,:rfp_id => #rfp.id,:project_id => #project do |b| %>
<%= b.hidden_field :rfp_id, :value => #rfp.id %>
<%= hidden_field_tag :project_id, #project %>
<table>
<tr> <td><b>Menutype </b></td>
<% if #rfp.menutype.present? %>
<td><%= #rfp.menutype %></td>
<td><%= b.number_field :menutype_est_hours %></td>
<% end %>
</tr>
<tr> <td> <b>Number of menu</b> </td>
<% if #rfp.numberofmenu.present? %>
<td><%= #rfp.numberofmenu %></td>
<td><%= b.number_field :numberofmenu_est_hours %></td>
<% end %>
</tr>
<tr>
<% #m1.map(&:id).each do |id|%>
<%= b.fields_for :modul1hours do |f| %>
<%= f.hidden_field :modul1_id, value => id %>
<%= f.text_field :module_est_hours, :size => 30 %>
</tr>
<% end %>
<% end %>
</table>
<%= b.submit 'Add Todo' %>
<% end %>
#esthour = Esthour.new
#gg = #esthour.modul1hours.build
#project = params[:project_id]
In this line:
<%= f.hidden_field :modul1_id, id %>
You are saying that you want the hidden field binded with modul1hour modul1_id method and options being id. Second parameter for FormBuilder hidden_field is expected to be a hash (which is then merged against default options). To do what you want do:
<%= f.hidden_field :modul1_id, value: id %>
Hidden fields aren't really the issue here
Apart from #BroiStatse's answer, I can see the issue as how you handle the params on your controller
Nested Models
Sending data to a controller sends that data to the relevant models. This is normally handled with accepts_nested_attributes_for, but can be handled manually too
From your controller code, I can't see how you're dealing with your extra data, but your error is caused by the incorrect merge of the params
Instead of saving the data manually, I would use the accepts_nested_attributes_for to save the data, like this:
#app/models/project.rb
Class Project < ActiveRecord::Base
accepts_nested_attributes_for :modul1hours
end
This will pass the params to your modul1hours model, where you'll then have to capture them with the relevant attr_accessible actions
f.fields_for
In order to get accepts_nested_attributes_for working properly, you have to ensure you use the f.fields_for function correctly.
You have to first build the ActiveRecord objects in your new controller action, like this:
def new
#project = Project.new
#project.modul1hours.build
end
Your problem is that you're then cycling through the ID's of your modul1hours model, yielding the f.fields_for artificially. Rails will only output an f.fields_for if the ActiveRecord object has been built in the controller:
"30" %>
This RailsCast gives you a better idea about this
What I would do is this:
#app/controllers/projects_controller.rb
def new
#project = Project.new
#m1.map(&:id).each do |i|
#project.modul1hours.build
end
end
#app/views/projects/new.html.erb
<%= b.fields_for :modul1hours do |f| %>
<%= hidden_field_tag :id, value :id %>
<%= f.text_field :module_est_hours, :size => "30" %>
<% end %>
I'm still thinking about how I would assign the ID's to the hidden field
Update
Try this:
#app/controllers/projects_controller.rb
def new
#project = Project.new
#project.modul1hours.build
end
Replace modul1hours with whatever your projects has_many of

Routing error in Rails embedded form

I have embedded a rails form as a simple dropdown menu in an html table. I have also implemented the form in such a way that whenever there is a change in the drop down menu then the form is submitted. But I am getting a routing error which I am trying to resolve.
The form code:
<td>
<%= form_for(lead, :action => 'update_lead_status', :html => {:id => 'lead_form'}, :remote => true) do |f| %>
<%= f.select(:status, ["to_call","called","confirmed","lite"], {:selected => lead.status}, :onchange => "$('#lead_form').submit();") %>
<% end %>
</td>
The routes.rb file:
get 'leads/:id/edit_lead_status' => "leads#edit_lead_status"
put 'leads/:id/update_lead_status'=> "leads#update_lead_status"
The leads_controller.rb file:
#PUT
def update_lead_status
#lead = Lead.find(params[:id])
respond_to do |format|
format.js
if #lead.update_attributes(params[:lead])
format.html { redirect_to leads_url, notice: 'Lead was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #lead.errors, status: :unprocessable_entity }
end
end
end
Also my embedded form in the table is at the /leads URL where I try to redirect on successful update.
The logs from my server:
ActionController::RoutingError (No route matches [PUT] "/leads/130"):
status is an accessible attribute in my leads model.
Please let me know where I am going wrong?
UPDATE:
So I tried sevenseacat's answer and it called my update_lead_status but with a wrong parameter. My table is like this:
<% #leads.each do |lead| %>
<tr>
<td><%= lead.id %></td>
<td><%= lead.prefix %></td>
<td><%= lead.name %></td>
<td><%= lead.mobile %></td>
<td><%= lead.phone %></td>
<td><%= lead.category %></td>
<td><%= lead.area %></td>
<td><%= lead.city %></td>
<td><%= lead.updated_at %></td>
<td><%= lead.is_valid %></td>
<td><%= lead.vendor_status %></td>
<td><%= lead.call_tries %></td>
<td>
<%= form_for(lead, url: update_lead_status_path(lead.id), :html => {:id => 'lead_form'}, :remote => true) do |f| %>
<%= f.select(:status, ["to_call","called","confirmed","lite"], {:selected => lead.status}, :onchange => "$('#lead_form').submit();") %>
<% end %>
</td>
<td><%= lead.remarks %><%= link_to lead.remarks, :controller => "leads", :action => "edit_lead_remarks", :id => lead, :remote => true %>
</td>
</tr>
<% end %>
Here for every row in the table it takes id as the id of the first lead in the table.
You're not specifying the action URL for the form properly - it should be for example form_for(lead, url: update_lead_status_path(lead))
(assuming you have named your route in your routes.rb, eg, as: :update_lead_status).
Try after adding following line of code in your routes.rb file.
resources :leads

Rails and SQLITE: Images are not being displayed

I am very new to Rails and Web-programming and hope you can help me out with my very first project.
I am developing a website for a Real Estate Agency.
I have 3 tables in my database (Homes: Home_ID, Home_Name, Admin_ID; Admins: Admin_ID, Admin_Name, Admin_Email; Images: Image_ID, Image_Path, Image_Name, Home_ID, Admin_ID).
All 3 tables have been created using scaffold. The image information (name, path, image_id, home_id etc) have been entered in SQLite.
I get all text information of the different houses displayed correctly on the website except the pictures.
My attempt to link it in the view/home/index.html.erb created the following error:
undefined method `image_path' for #<Home:0xb63d85e0>
I used below code:
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= home.image_path %></td>
</tr>
<% end %>
</table>
It looks like that the data entered in SQLite do not sync with rails.
Do you have any idea what I have done wrong and how I can fix it?
Thank you.
I'm not positive what the relationship would be between your images and home models would be so correct me if I'm wrong, but I'm guessing that homes will have many images. Each image would belong to one home. Is this correct? If so, you will need to declare that in your models like so:
models/home.rb
has_many :images
models/image.rb
belongs_to :home
You will then need to add this to the image database:
t.integer "home_id"
You can add it by going to the command line and typing:
rails g migration AddHomeToImages home_id:integer
You should look in db/migrate/ and then the most recent migration file and make sure it looks like this:
add_column :images, :home_id, :integer
Then run:
rake db:migrate
At this point you'll only need to update your controller and views to show this association. Let me know if this helps and if so I'll help you with your controller and views.
What's happening is that you are looping through a selection of records from the Home table. Because of this, when you call
<td><%= home.image_path %></td>
it's not recognizing the attribute image_path because you don't have image_path as a column of Home table. You only have Home_ID, Home_Name, Admin_ID for your columns. You will have to look into associations between models in order to figure out how to grab the image_path for each home record. You can start here.
If you update the code later on I'll be glad to comment on it.
I think that the best solution here will be to use paperclip gem.
You can take a look at this very old railscast eoisode just to understand how it works:
http://railscasts.com/episodes/134-paperclip
And here is github repository:
https://github.com/thoughtbot/paperclip
Paperclip will help you with paths, styles and preview for your images.
Thanks Jason,
I agree that it is a bit big for newbies, but the requirements were that we do a website where we need to read and write from/to a database. We had a quick introduction to rails with partnerwork and are now on our own and a "bit" lost and running out of time.
Here is the error message I am getting:
NameError in Homes#index
undefined local variable or method `image' for
<#:0xb62f7aa4>
Extracted source (around line #20):
17: <% #homes.each do |home| %>
18: <tr>
19: <td><%= home.name %></td>
20: <td><%= image.home_id %></td>
21: <td><%= home.details %></td>
22: <td><%= home.region %></td>
23: <td><%= home.address %></td>
When I create the database tables I had an Image_ID in the homes table, but I was told that I don`t need it and that it is enough to have only Home_ID in the images table.
I understand that the error is caused because of image.home_id.
What is your opinion? Should I add the Image_ID back to the homes table in order to display all images for the respective home_id or is there another way? I would like to be able to decide which picture will be displayed as the main picture and which ones as the smaller pictures.
Here is the code I use:
models/home.rb
class Home < ActiveRecord::Base
attr_accessible :address, :admin_id, :details, :name, :price, :region
has_many :images
end
models/image.rb
class Image < ActiveRecord::Base
attr_accessible :image_description, :image_name, :image_path
belongs_to :home
end
views/homes/index.html.erb
<h1>Listing homes</h1>
<table>
<tr>
<th>Name</th>
<th>Image</th>
<th>Details</th>
<th>Region</th>
<th>Address</th>
<th>Price</th>
<th>Admin</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= image.home_id %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= link_to 'Show', home %></td>
<td><%= link_to 'Edit', edit_home_path(home) %></td>
<td><%= link_to 'Destroy', home, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Home', new_home_path %>
views/homes/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #home.name %>
</p>
<p>
<b>Image:</b>
<%= #image.home_id %>
</p>
<p>
<b>Details:</b>
<%= #home.details %>
</p>
<p>
<b>Region:</b>
<%= #home.region %>
</p>
<p>
<b>Address:</b>
<%= #home.address %>
</p>
<p>
<b>Price:</b>
<%= #home.price %>
</p>
<p>
<b>Admin:</b>
<%= #home.admin_id %>
</p>
<%= link_to 'Edit', edit_home_path(#home) %> |
<%= link_to 'Back', homes_path %>
views/images/_form.html.erb
<%= form_for(#image) do |f| %>
<% if #image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#image.errors.count, "error") %> prohibited this image from being saved:</h2>
<ul>
<% #image.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :image_name %><br />
<%= f.text_field :image_name %>
</div>
<div class="field">
<%= f.label :image_path %><br />
<%= f.text_field :image_path %>
</div>
<div class="field">
<%= f.label :image_description %><br />
<%= f.text_area :image_description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
controllers/images_controller.rb
class ImagesController < ApplicationController
# GET /images
# GET /images.json
def index
#images = Image.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #images }
end
end
# GET /images/1
# GET /images/1.json
def show
#image = Image.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #image }
end
end
# GET /images/new
# GET /images/new.json
def new
#image = Image.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #image }
end
end
# GET /images/1/edit
def edit
#image = Image.find(params[:id])
end
# POST /images
# POST /images.json
def create
#image = Image.new(params[:image])
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render json: #image, status: :created, location: #image }
else
format.html { render action: "new" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PUT /images/1
# PUT /images/1.json
def update
#image = Image.find(params[:id])
respond_to do |format|
if #image.update_attributes(params[:image])
format.html { redirect_to #image, notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1
# DELETE /images/1.json
def destroy
#image = Image.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to images_url }
format.json { head :no_content }
end
end
end
Thank you so much. I really appreciate your help!!!

How can I pass the parameters to controller correctly?

From show view: I'd like to pass the shown message's id to discard action and trash the message.
From index view: I'd like to pass the checked messages' ids to discard action and trash them all at once.
But I only can trash one record at once even if I check multiple and submit from index view.
How can I archive both 1 and 2 with the same action????
Routes
match 'messages/discard(/:id)' => 'messages#discard', :via => :post , :as => :discard_messages
index view
<%= form_tag(:action => discard, :via => 'post') do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag "id",m.id %></td>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at.to_s(:jp) %></td>
<td><%= m.last_sender.username %></td>
<td><%= link_to m.subject, show_messages_path(:id => m, :breadcrumb => #box) %></td>
</tr>
<% end %>
<%= submit_tag "discard", :class => 'btn' %>
<% end %>
show view
<%= link_to 'Discard', discard_messages_path(#messages), :class => 'btn', :method => 'post' %>
controller
def discard
conversation = Conversation.find_all_by_id(params[:id])
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to :back
end
use the [] naming in your html, which rails will then make available as an array in the params
index.html.erb
<td><%= check_box_tag "message_id[]", m.id %></td>
controller
# ...
else
conversations = Conversation.where("id IN (?)", params[:message_id][])
# ...
to simplify things further I would remove the conditional in your action and create two separate actions
routes
resource :messages do
member do
post 'discard' # /messages/:id/discard
end
collection do
post 'discard_all' # /messages/discard_all?message_id[]=1&message_id[]=22
end
end

Simple quantity function problems, shopping cart

I just picked up Agile Web Development with Rails 3rd Ed., and I'm going thru the Depot Application chapters, I'm attempting to create a simple Edit quantity function, and delete function. I've had luck with the delete function but no luck with the edit quantity function.
I'm going to provide a lot of information, so please don't feel overwhelmed. I've found this to be a challenging problem.
To add_to_cart.html.erb
<div class="cart-title">Your cart</div>
<table>
<% for item in #cart.items %>
<tr>
<td><% form_for #cart.items, :url => {:action => "cart_update", :id => "#{item.getinventoryid}"} do |f| %>
<%= f.text_field :quantity, :size => '3' %>
<%= f.hidden_field :id, :value => "#{item.getinventoryid}" %>
<%= f.submit 'cart_update' %>
<% end %></td>
<td><%=h item.quantity %> ×</td>
<td><%=h item.title %></li></td>
<td><%=h item.description %></td>
<td class="item-price"><%= number_to_currency(item.price) %></td>
<td><%= link_to 'remove', {:controller => 'inventories', :action => 'remove_cart_item', :id => "#{item.getinventoryid}"} %></td>
</tr>
<% end %>
<tr class="total-line">
<td colspan="4">Total</td>
<td class="total-cell"><%= number_to_currency(#cart.total_price) %></td>
</tr>
</table>
<%= button_to "Checkout", :action => 'checkout' %>
<%= button_to 'Empty cart', :action => 'empty_cart' %>
inventories_controller:
def cart_update
#inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.increment_inventory_quantity(params[:inventory])
end
def remove_cart_item
inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.remove_inventory(inventory)
redirect_to_index("The item was removed")
end
Cart.rb model
attr_accessor :items
def increment_inventory_quantity(id, quantity)
inventory_to_increment = #items.select{|item| item.inventory == inventory}
# We do this because select will return an array
unless product_to_increment.empty?
inventory_to_increment = inventory_to_increment.first
else
# error handling here
end
inventory_to_increment.quantity = quantity
end
def remove_inventory(inventory)
#items.delete_if {|item| item.inventory == inventory }
end
cart_item.rb model
attr_accessor :inventory, :quantity
def getinventoryid
#inventory.id
end
This produces strange results:
Notice the quantity 16 appears in both items from my loop (#Fail). When I submit the form a ArgumentError in InventoriesController#cart_update wrong number of arguments (1 for 2) error is returned. Parameters being passed:
{"commit"=>"cart_update",
"_method"=>"put",
"authenticity_token"=>"sH1tWXTJPltpSq5XaAkww7259IR5ZiflnqSFB2Zb0IY=",
"id"=>"50",
"cart_item"=>{"quantity"=>"16",
"id"=>"50"}}
You are getting the wrong number of arguments error because you are passing one argument to #cart.increment_inventory_quantity in the controller method. That method requires two arguments.
# In your controller:
def cart_update
#inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.increment_inventory_quantity(params[:inventory]) # you are passing one thing
end
# Then in your model:
def increment_inventory_quantity(id, quantity) # the method wants two things
# ...
Possibly you intended to do something like this:
def cart_update
#inventory = Inventory.find(params[:cart_item][:id])
#cart = find_cart
#cart.increment_inventory_quantity(#inventory.id, params[:cart_item][:quantity])
end
Are you sure it's form_for( #cart.items ) and not form_for( item )?

Resources