I'm trying to be on that page right before the checkout, where you can modify the quantity and update all the prices accordingly. Now my "Update" button, updates 'something' but it's not what i'm trying to achieve, it sends me on a line_items show page that i don't even want to have (i'm keeping it for now to avoid the missing template error). The rails documentation isn't helping me ... well anyway, the code is this
<ul>
<% #cart.line_items.each do |item| %>
<%= form_for(item) do |f| %>
<li><%= f.number_field :quantity, :value => item.quantity %> x <%= item.product.name %>
<%= item.total_price %> </li>
<% end %>
<%= submit_tag "Update" %>
<% end %>
<br><strong>Total Price:</strong> <%= #cart.total_price %>
</ul>
<%= button_to "Checkout", new_order_path, method: :get, data: { confirm: "Are you sure?" } %>
<%= button_to 'Empty cart', #cart, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to 'Back', categories_path %>
Thank you !
edited
class LineItemsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:create, :update, :destroy]
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
# GET /line_items
# GET /line_items.json
def index
#line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show
end
# GET /line_items/new
def new
#line_item = LineItem.new
end
# GET /line_items/1/edit
def edit
end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
#line_item = #cart.add_product(product.id)
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item.cart, notice: 'Line item was successfully created.' }
format.json { render :show, status: :created, location: #line_item }
else
format.html { render :new }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
respond_to do |format|
if #line_item.update(line_item_params)
format.html { redirect_to #cart, notice: 'Line item was successfully updated.' }
format.json { render :show, status: :ok, location: #line_item }
else
format.html { render :edit }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
#line_item.destroy
respond_to do |format|
format.html { redirect_to line_items_url, notice: 'Line item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
#line_item = LineItem.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_item_params
params.require(:line_item).permit(:product_id, :cart_id, :order_id)
end
end
Just do redirect after you update an item. And provide correct line_item_update_params method that permites quantity param. Your controller should look like that:
class ItemsController < ApplicationController
def update
item = Item.find(params[:id])
item.update(line_item_update_params)
redirect_to :back # this is the key line of code
end
...
private
# it is used for creating
def line_item_params
params.require(:line_item).permit(:product_id, :cart_id, :order_id)
end
# it is used for updating
def line_item_update_params
params.require(:line_item).permit(:quantity)
end
...
end
Related
I have a problem with a simple browser in my application.
I have already looked for solutions but still displays the following error:
param is missing or the value is empty: expense.
Please help.
Index:
<%= form_tag expenses_path :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" , name: nil %>
Controller:
class ExpensesController < ApplicationController
before_action :set_expense, only: [:show, :edit, :update, :destroy]
# GET /expense expense
# GET /expense.json
def index
#expenses = Expense.search(params[:search])
end
# GET /expense/1
# GET /expense/1.json
def show
end
# GET /expense/new
def new
#expense = Expense.new
end
# GET /expense/1/edit
def edit
end
# POST /expense
# POST /expense.json
def create
#expense = Expense.new(expense_params)
respond_to do |format|
if #expense.save
format.html { redirect_to #expense, notice: 'zostały zapisane.' }
format.json { render :show, status: :created, location: #expense }
else
format.html { render :new }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /expense/1
# PATCH/PUT /expense/1.json
def update
respond_to do |format|
if #expense.update(expense_params)
format.html { redirect_to #expense, notice: 'expense was successfully updated.' }
format.json { render :show, status: :ok, location: #expense }
else
format.html { render :edit }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
# DELETE /expense/1
# DELETE /expense/1.json
def destroy
#expense.destroy
respond_to do |format|
format.html { redirect_to #expense, notice: 'Zakupy zostały usunięte.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_expense
#expense = Expense.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def expense_params
params.require(:expense).permit(:date, :price, :category, :where)
end
Expense.rb:
class Expense < ApplicationRecord
def self.search(search)
if search
where (['where LIKE ?',"%#{search}%"])
else
all
end
end
permit the search in your params
def expense_params
params.require(:expense).permit(:date, :price, :category, :where, :search)
end
please correct the form_tag syntax
<%= form_tag(expenses_path,method: :get) do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" , name: nil %>
<% end %>
The error message you report is most likely coming from your expense_params method:
params.require(:expense) means you expect the parameters to be of the form params[:expense][:date], params[:expense][:price], etc.
My best guess is that your form is not actually submitting a GET request and so it's going to the create method rather than the index method.
I think this may be occurring because you are missing a comma between expenses_path and :method => 'get' in your form_tag. It should be:
<%= form_tag expenses_path, :method => 'get' do %>
I need to multiple delete tasks with checkboxes, when i do this have an error
Have tasks and checkboxes for every task, when clicked on checkbox and then click the "Delete selected" button it must be deleted all checked tasks
NoMethodError in TasksController#delete_multiple
undefined method `destroy'
here is my request
{"utf8"=>"✓",
"_method"=>"delete",
"authenticity_token"=>"Bc2lZKUDVOjkQ0DYTDNI8TVliMaDKb+z2wz46RJeFqFol8WyEABA8sAz+WPCQOD2V0SEyqSHAryuoYQ6nvk4sA==",
"cb_tasks"=>["1", "3", "4"],
"commit"=>"Delete selected"}
and
my task_controller
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
# multiple delete with checkboxes
def delete_multiple
#tasks = Task.find(params[:cb_tasks])
#tasks.destroy() // **here is a problem**
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Tasks was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:title, :description, :priority, :due, :done)
end
end
my task.rb
class Task < ApplicationRecord
def destroy
Task.find(params[:cb_tasks]).destroy
flash[:success] = "Material destroyed."
redirect_to tasks_url
end
end
my index.html.rb
<%= form_tag delete_multiple_tasks_path, method: :delete do %>
<div class="CSSTableGenerator" >
<table >
<tr>
<td>Tasks</td>
</tr>
<% #tasks.each do |task| %>
<tr>
<td><%= check_box_tag "cb_tasks[]", task.id %></td>
<td><%= link_to task.title, task %></td>-->
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task, method: :delete, data: {confirm: 'Are you sure?'} %></td>
</tr>
<% end %>
</table>
</div>
<%= submit_tag "Delete selected" %>
<% end %>
my routes
resources :tasks do
collection do
delete 'delete_multiple'
end
end
Why it can't undefined method `destroy' ?
Can anyone help me?
The problem is below line
#tasks = Task.find(params[:cb_tasks])
#tasks.destroy() // **here is a problem**
You can modify this like below
Task.where(id: params[:cb_tasks]).destroy_all
I think will help
instead of overwrite destroy method in model side you can do this and i would suggest you not to overwrite destroy however if you overwrite destroy method than you are not passing params[:cb_tasks] to this method and in Task.find(params[:cb_tasks]).destroy this line fails to execute because it does not get params[:cb_tasks] here in model
so you can do this like -
def delete_multiple
#tasks = Task.find(params[:cb_tasks])
#tasks.destroy_all // **replace it**
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Tasks was successfully destroyed.' }
format.json { head :no_content }
end
end
I find how it just works. I deleted method destroy the model
and in controller do this
def delete_multiple
Task.where(id: params[:cb_tasks]).destroy_all
end
Thanks for all your answers, you are the best!
sorry for this question but I'm struggling with this issue for hours now and can't find the answer anywhere.
Here is the thing, I have a rails app with "Reservation" and "Space" models with the following relations:
class Reservation < ActiveRecord::Base
belongs_to :space
belongs_to :user
end
class Space < ActiveRecord::Base
belongs_to :condo
has_many :reservations
end
When the user creates a new Reservation, in the form he gets to choose from a dropdown (f.select) the spaces available for him. The f.select in the form look like this:
<div class="field">
<%= #user_spaces = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user_spaces, :id, :name), :prompt => "Select space"
%>
</div>
That select it supose to assign a value to the key "space_id" in the Reservation that is being created (column's table is created). But when I check the last reservation in Rails console, space_id value is "nil". What am I doing wrong?
Thank you very much for your help
Reservation controller file:
class ReservationsController < ApplicationController
before_action :set_reservation, only: [:show, :edit, :update, :destroy]
# GET /reservations
# GET /reservations.json
def index
#reservations = Reservation.all
end
# GET /reservations/1
# GET /reservations/1.json
def show
end
# GET /reservations/new
def new
#reservation = Reservation.new
end
# GET /reservations/1/edit
def edit
end
# POST /reservations
# POST /reservations.json
def create
#reservation = Reservation.new(reservation_params)
#user = current_user.id
#reservation.user_id = #user
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reservations/1
# PATCH/PUT /reservations/1.json
def update
respond_to do |format|
if #reservation.update(reservation_params)
format.html { redirect_to #reservation, notice: 'Reservation was successfully updated.' }
format.json { render :show, status: :ok, location: #reservation }
else
format.html { render :edit }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reservations/1
# DELETE /reservations/1.json
def destroy
#reservation.destroy
respond_to do |format|
format.html { redirect_to reservations_url, notice: 'Reservation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reservation
#reservation = Reservation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:eventdate)
end
end
Space controller file:
class SpacesController < ApplicationController
before_action :set_space, only: [:show, :edit, :update, :destroy]
# GET /spaces
# GET /spaces.json
def index
#spaces = Space.all
end
# GET /spaces/1
# GET /spaces/1.json
def show
end
# GET /spaces/new
def new
#space = Space.new
end
# GET /spaces/1/edit
def edit
end
# POST /spaces
# POST /spaces.json
def create
#space = Space.new(space_params)
respond_to do |format|
if #space.save
format.html { redirect_to #space, notice: 'Space was successfully created.' }
format.json { render :show, status: :created, location: #space }
else
format.html { render :new }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /spaces/1
# PATCH/PUT /spaces/1.json
def update
respond_to do |format|
if #space.update(space_params)
format.html { redirect_to #space, notice: 'Space was successfully updated.' }
format.json { render :show, status: :ok, location: #space }
else
format.html { render :edit }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# DELETE /spaces/1
# DELETE /spaces/1.json
def destroy
#space.destroy
respond_to do |format|
format.html { redirect_to spaces_url, notice: 'Space was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_space
#space = Space.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def space_params
params.require(:space).permit(:name)
end
end
And full Reservation Form:
<%= form_for(#reservation) do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :eventdate %><br>
<%= f.date_select :eventdate %>
</div>
<div class="field">
<%= #user = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user, :id, :name), :prompt => "Select space"
%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pretty sure you need to permit the space_id attribute in your strong params.
def reservation_params
params.require(:reservation).permit(:eventdate, :space_id)
end
whats happening is that when you go to create a reservation, youre passing in set of params, that is the output of reservation_params
#reservation = Reservation.new(reservation_params)
if space_id is not being permitted in your strong params, then it will be nil when created.
if this is not the issue, can you post what params are getting to the server, and what the output of reservation_params are.
So I'm learning rails via writing some simple application and in that app I have two types of objects: Tasks and Projects.Sense is that all those objects can be created by user,user must be able to manipulate them and so on.Each task belongs_to project and project has_many tasks.But when I create new project - it already has all tasks from all another projects,so it looks like:
This '123' task was created by simply adding task to 'Project' but same task still appear in 'Another project'.How can I fix this bug and make my task unique?I think something must be added to task or projects model
but I don't know what should I add.
Here are corresponding models and controllers:
Task.rb
class Task < ActiveRecord::Base
belongs_to :project
end
Project.rb
class Project < ActiveRecord::Base
belongs_to :user
has_many :tasks, dependent: :destroy
validates :name, presence: true, uniqueness: true
end
tasks_controller.rb
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to home_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to home_url }
format.json { render :home_url, status: :ok, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to home_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:deadline, :name)
end
end
projects_controller.rb
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
# GET /projects
# GET /projects.json
def index
#projects = Project.all
end
# GET /projects/1
# GET /projects/1.json
def show
end
# GET /projects/new
def new
#project = Project.new
end
# GET /projects/1/edit
def edit
end
# POST /projects
# POST /projects.json
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to home_url }
format.json { render :show, status: :created, location: #project }
else
format.html { render :home_url }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projects/1
# PATCH/PUT /projects/1.json
def update
respond_to do |format|
if #project.update(project_params)
format.html { redirect_to home_url }
format.json { render :show, status: :ok, location: #project }
else
format.html { render :home_url }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.json
def destroy
#project.destroy
respond_to do |format|
format.html { redirect_to home_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project
#project = Project.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_params
params.require(:project).permit(:name)
end
end
task view -
<% #tasks.each do |task| %>
<div class="row task">
<div class="col-xs-12">
<div class="col-xs-1 checkbox">
<%= check_box_tag 'accept' %>
</div>
<div class="col-xs-8 taskbody">
<%= task.name %>
</div>
<div class="mini-glyph">
<div class="col-xs-1">
<span class="glyphicon glyphicon-arrow-up"></span>
<span class="glyphicon glyphicon-arrow-down"></span>
</div>
<div class="col-xs-1">
<%= link_to edit_task_path(task) do %>
<span class="glyphicon glyphicon-pencil"></span>
<% end %>
</div>
<div class="col-xs-1">
<span><%= link_to " ", task, method: :delete, data: { confirm: 'Are you sure?' }, class:"glyphicon glyphicon-trash" %></span>
</div>
</div>
</div>
</div>
<% end %>
To set the project_id when you create a task, add something like this to your form:
<%= f.select :project_id, options_for_select(Project.choices) %>
then in project.rb
def self.choices
all_projects = []
Project.find_each do |project|
# show the name but save the id
all_projects << [project.name, project.id]
end
all_projects
end
Then change display the tasks with Task.where(project_id: project_id) instead of Task.all as the first two comments suggest.
I have nested resources - users have_many manufacturers and manufacturers have_many lines. I wrote a before_filter to load the #manufacturer so it could go through the rest of the functions in the lines_controller. Problem is, I'm running into issues when I click edit on the lines/show view.
Error: Couldn't find Manufacturer with id=manufacturer_id
77 def load_manufacturer
78 #manufacturer = Manufacturer.find(params[:manufacturer_id])
79 end
So here's what I'm working with:
app/views/lines/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #line.name %>
</p>
<p>
<strong>Manufacturer:</strong>
<%= #line.manufacturer_id %>
</p>
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %> |
<%= link_to 'Back', manufacturer_lines_path(#line.manufacturer_id) %>
lines_controller.rb
class LinesController < ApplicationController
before_action :set_line, only: [:show, :edit, :update, :destroy]
before_filter :load_manufacturer
# GET /lines
# GET /lines.json
def index
#lines = Line.all
end
# GET /lines/1
# GET /lines/1.json
def show
end
# GET /lines/new
def new
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#line = #manufacturer.lines.build
end
# GET /lines/1/edit
def edit
end
# POST /lines
# POST /lines.json
def create
#line = #manufacturer.lines.build(line_params)
respond_to do |format|
if #line.save
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully created.' }
format.json { render action: 'show', status: :created, location: #line }
else
format.html { render action: 'new' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /lines/1
# PATCH/PUT /lines/1.json
def update
respond_to do |format|
if #line.update(line_params)
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lines/1
# DELETE /lines/1.json
def destroy
#line.destroy
respond_to do |format|
format.html { redirect_to manufacturer_lines_url(#manufacturer) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line
#line = Line.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_params
params.require(:line).permit(:name, :manufacturer_id)
end
def load_manufacturer
#manufacturer = Manufacturer.find(params[:manufacturer_id])
end
end
This:
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %>
Should be
<%= link_to 'Edit', edit_manufacturer_line_path(#manufacturer,#line) %>
What is happening is it is changing the symbol :manufacturer_id to a string and passing it to the route so your route looks like
`/manufacturers/manufacturer_id/lines/###/edit`
when you want
/manufacturers/###/lines/###/edit