want to increment repeated items on my shopping app
so when a users places an order and then wants to edit the order he can change the order quantities.
At the moment when i click on the quantity (i have set the quantity to 1) It goes to the order_itmes editing screen - it allows me to update the order but when i click submit get an error
NameError in OrderItemsController#update
#order_item = OrderItem.find(params[:id])
respond_to do |format|
if order_item.params[:quantity].to_i == 0 **<-----Error**
#order_item.destroy
format.html { redirect_to #order_item.order, notice: 'Item was deleted from your cart.' }
format.json { head :no_content }
parameters
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"/8xRjbtusgdLV5SVQP55aUDccYdUzB9G23heTtEeNfk=",
"order_item"=>{"quantity"=>"2"},
"commit"=>"Update Order item",
"id"=>"68"}
order_items controller
class OrderItemsController < ApplicationController
before_action :set_order_item, only: [:show, :edit, :destroy]
before_action :load_order, only: [:create]
# GET /order_items/1/edit
def edit
end
# POST /order_items
# POST /order_items.json
def create
#order_item = #order.order_items.find_or_initialize_by_product_id(params[:product_id])
#order_item.quantity += 1
respond_to do |format|
if #order_item.save
format.html { redirect_to #order, notice: 'Successfully Added Product To Cart.' }
format.json { render action: 'show', status: :created, location: #order_item }
else
format.html { render action: 'new' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /order_items/1
# PATCH/PUT /order_items/1.json
def update
#order_item = OrderItem.find(params[:id])
respond_to do |format|
if order_item.params[:quantity].to_i == 0
#order_item.destroy
format.html { redirect_to #order_item.order, notice: 'Item was deleted from your cart.' }
format.json { head :no_content }
elsif #order_item.update(order_item_params)
format.html { redirect_to #order_item.order, notice: 'Successfully updated the order item.' }
else
format.html { render action: 'edit' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /order_items/1
# DELETE /order_items/1.json
def destroy
#order_item.destroy
respond_to do |format|
format.html { redirect_to #order_item.order }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order_item
#order_item = OrderItem.find(params[:id])
end
def load_order
#order = Order.find_or_initialize_by_id(session[:order_id], status: "Unsubmitted", user_id: session[:user_id])
if #order.new_record?
#order.save!
session[:order_id] = #order.id
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_item_params
params.require(:order_item).permit(:product_id, :order_id, :quantity)
end
end
order.controller
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy, :confirm]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params.merge(status: 'submitted'))
format.html { redirect_to confirm_order_path(#order), notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to products_path }
format.json { head :no_content }
end
end
def confirm
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:user_id, :status, :address_id)
end
end
order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
validates :order_id, :product_id, presence: true
validates :quantity, numericality: { only_integer: true, greater_than: 0 }
def subtotal
quantity * product.price
end
end
just seen it if order_item.params[:quantity].to_i == 0
should be if order_item_params[:quantity].to_i == 0
Related
I'm learning ROR. Trying to build this model: one user can have many store each store can have many product. I've been able to create store linking to its owner but I'm stuck at doing the same for product.
store.rb
class Store < ApplicationRecord
belongs_to :user
has_many :products, :foreign_key => :store_id
end
product.rb
class Product < ApplicationRecord
belongs_to :store
end
products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:product_name, :product_price, :product_description, :product_tag, :sku_code)
end
end
stores_controller.rb
class StoresController < ApplicationController
before_action :set_store, only: [:show, :edit, :update, :destroy]
# GET /stores
# GET /stores.json
def index
#stores = Store.all
end
# GET /stores/1
# GET /stores/1.json
def show
#products = Product.all
end
# GET /stores/new
def new
#store = Store.new
end
# GET /stores/1/edit
def edit
end
# POST /stores
# POST /stores.json
def create
#store = Store.new(store_params)
#store.user_id = current_user.id
respond_to do |format|
if #store.save
format.html { redirect_to #store, notice: 'Store was successfully created.' }
format.json { render :show, status: :created, location: #store }
else
format.html { render :new }
format.json { render json: #store.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /stores/1
# PATCH/PUT /stores/1.json
def update
respond_to do |format|
if #store.update(store_params)
format.html { redirect_to #store, notice: 'Store was successfully updated.' }
format.json { render :show, status: :ok, location: #store }
else
format.html { render :edit }
format.json { render json: #store.errors, status: :unprocessable_entity }
end
end
end
# DELETE /stores/1
# DELETE /stores/1.json
def destroy
#store.destroy
respond_to do |format|
format.html { redirect_to stores_url, notice: 'Store was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_store
#store = Store.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def store_params
params.require(:store).permit(:store_name, :store_description)
end
end
I expect when creating a product, it will get the store_id immediately. I'm keep getting "store must exist" message
From Rails 5, belongs_to requires the association object to be present. If your product object does not have a valid store_id (nil or inexistent store object), that product object will not be valid.
You can bypass this by allowing the association to be optional
class Product < ApplicationRecord
belongs_to :store, optional: true
end
Or, you should allow store_id as permitted parameter in your products_controller and pass it when you create a new product
# below code I assume that your store table has a column called 'store_name'
<%= form_for #product do |f| %>
<%= f.collection_select :store_id, current_user.stores, :id, :store_name, prompt: 'Please select the store of this product' %>
<%= f.submit %>
<% end %>
I have three models:
Tracks, LineItems and Cart
By using line item associations, I'm adding tracks (for purchase) to a cart. Yet when I click 'add to cart' the following error message gets thrown:
No route matches [POST] "/line_items/1"
Despite extensively reviewing my code; I can't seem to find the problem, is it in my controller for line_items? It appears as though it is trying to post a line_item with id = 1 which doesn't exist?
line_items_controller.rb
class LineItemsController < ApplicationController
include CurrentCart
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
before_action :set_cart, only: [:create]
# 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
#track = Track.find(params[:track_id])
#line_item = #cart.add_track(track)
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item, 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 #line_item, 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
#cart = Cart.find(session[:cart_id])
#line_item.destroy
respond_to do |format|
format.html { redirect_to cart_path(#cart), 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(:track_id)
end
end
carts_controller.rb
class CartsController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with :invalid_cart
before_action :set_cart, only: [:show, :edit, :update, :destroy]
# GET /carts
# GET /carts.json
def index
#carts = Cart.all
end
# GET /carts/1
# GET /carts/1.json
def show
end
# GET /carts/new
def new
#cart = Cart.new
end
# GET /carts/1/edit
def edit
end
# POST /carts
# POST /carts.json
def create
#cart = Cart.new(cart_params)
respond_to do |format|
if #cart.save
format.html { redirect_to #cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: #cart }
else
format.html { render :new }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /carts/1
# PATCH/PUT /carts/1.json
def update
respond_to do |format|
if #cart.update(cart_params)
format.html { redirect_to #cart, notice: 'Cart was successfully updated.' }
format.json { render :show, status: :ok, location: #cart }
else
format.html { render :edit }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# DELETE /carts/1
# DELETE /carts/1.json
def destroy
#cart.destroy if cart.id == session[:cart_id] #hook into current client session instead of user
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to root-path, notice: 'Cart was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cart
#cart = Cart.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cart_params
params.fetch(:cart, {})
end
def invalid_cart
logger.error "Attempt to access invalid cart #{params[:id]}"
redirect_to root_path, notice: "That cart doesn't exist"
end
end
views > carts > show.html.haml
.keep-shopping.pv1.mt4.has-text-right
= link_to 'Keep Shopping', tracks_path, class: 'button is-warning'
%hr/
%section.section
= render(#cart.line_items)
.columns
.column
= button_to 'Empty Cart', #cart, method: :delete, data: { confirm: "Are you sure? " }, class: "button is-danger"
.column.total.has-text-right
%h4.title.is-4
%span.f5.has-text-grey Total:
= number_to_currency(#cart.total_price)
views > _line_items.html.haml (line helper partial)
.columns.align-items-center
.column.is-1
= line_item.quantity
.column.is-2
%figure.is-128x128.image
= image_tag(line_item.track.image_url(:thumb))
.column.is-9
%strong= line_item.track.name
.columns.align-items-center
.content.column.is-9
= truncate(line_item.track.description, length: 140)
.column.is-3.has-text-right
%strong.f4= number_to_currency(line_item.total_price)
.has-text-right
= link_to 'Remove Item', line_item, method: :delete, data: { confirm: "Are you sure? " }, class: "button is-small mb4"
= succeed "/" do
%hr/
I have come across this issue before. I am most definitely from your "add to cart button". I suppose your LineItem belongs_to The Cart and the product. If so when you're passing your button data to your line_item "add to cart" button, you might wanna set the current cart also so that you send over both IDs.
If possible you might want to share more code snippets of your button and your relationships.
I have a list of posts and all of them can be votable. I can count the number of votes for each post, but how can I count the number for all of them? I'm using the gem acts_as_votable for the voting system
I count the number of posts like this: <%= performance_indicator.improvement_actions.count %>
this is my "posts" controller:
class ImprovementActionsController < ApplicationController
before_action :set_improvement_action, only: [:show, :edit, :update, :destroy, :upvote, :downvote]
before_action :authenticate_user!, except: [:index, :show]
# GET /improvement_actions
# GET /improvement_actions.json
def index
end
# GET /improvement_actions/1
# GET /improvement_actions/1.json
def show
end
# GET /improvement_actions/new
def new
#performance_indicator = PerformanceIndicator.find(params[:performance_indicator_id])
#improvement_action = ImprovementAction.new
#comment = #improvement_action.comments.new
end
# GET /improvement_actions/1/edit
def edit
end
# POST /improvement_actions
# POST /improvement_actions.json
def create
#performance_indicator = PerformanceIndicator.find(params[:performance_indicator_id])
#improvement_action = #performance_indicator.improvement_actions.create(params[:improvement_action].permit(:description))
#improvement_action.user_id = current_user.id if current_user
#improvement_action.save
respond_to do |format|
if #improvement_action.save
format.html { redirect_to #performance_indicator }
format.json { render :show, status: :created, location: #improvement_action }
else
format.html { render :new }
format.json { render json: #improvement_action.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /improvement_actions/1
# PATCH/PUT /improvement_actions/1.json
def update
respond_to do |format|
if #improvement_action.update(improvement_action_params)
format.html { redirect_to performance_indicator_path(#improvement_action.performance_indicator), notice: 'Improvement action was successfully updated.' }
format.json { render :show, status: :ok, location: #performance_indicator }
else
format.html { render :edit }
format.json { render json: #improvement_action.errors, status: :unprocessable_entity }
end
end
end
def destroy
#improvement_action.destroy
respond_to do |format|
format.html { redirect_to performance_indicator_path(#improvement_action.performance_indicator), notice: 'Improvement action was successfully deleted.' }
format.json { head :no_content }
end
end
#upvote_from user
#downvote_from user
def upvote
#improvement_action.upvote_from current_user
# respond_to do |format|
# format.html { redirect_to :back }
# format.js { render layout: false }
# end
redirect_to :back
end
def downvote
#improvement_action.downvote_from current_user
redirect_to :back
##respond_to do |format|
# format.html { redirect_to :back }
# format.js { render layout: false }
# end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_improvement_action
#improvement_action = ImprovementAction.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def improvement_action_params
params.require(:improvement_action).permit(:description, :upvote, :downvote, :score, :active)
end
end
And I want to put here the counter:
<% #performance_indicators.each do |performance_indicator| %>
<p> Number of votes </p>
<% end %>
Do you have any cache column for votes in the ImprovementAction model? (https://github.com/ryanto/acts_as_votable#caching)
It is for keeping total amount of votes for each post. You should have it to do the calculation you want:
# in this case the cache column is :cached_votes_total
sum = performance_indicator.improvement_actions.sum(:cached_votes_total)
This will make only one database request.
Never do like this:
# DON'T DO THIS !!!
performance_indicator.improvement_actions.inject(0) {|sum, post| sum + post.votes_for.size }
This will have to load and instantiate all the records and make a separate request for each of them to retrieve their votes. Very BAD solution !
My issue is, when I am under the camper show page
Current Camper URL:
campers/1
and I go to click on to view the appointment it uses the camper_id for the appointment_id which is wrong so say if the camper_id is 1 it will use the appointment_id as 1 and actually the appointment id is 3, so then it says Couldn't find appointment with id of 1.
Table Header
<% #appointments.each do |app| %>
<%= link_to app.camper.camperName, appointment_path(#camper, #appointment) %>
Campers Controller Show Action
#appointments = #camper.appointments
Camper Model
has_many :appointments, dependent: :destroy
Appointment Model
belongs_to :camper
Shallow Nested Routes File
resources :customers, shallow: :true do
resources :campers do
resources :appointments do
resources :orders do
member do
patch :complete
end
end
end
end
end
Camper Controller
class CampersController < ApplicationController
before_action :set_camper, only: [:show, :edit, :update, :destroy]
# before_action :set_customer, only: [:index, :new, :edit, :create, :update]
load_and_authorize_resource
# GET /campers
# GET /campers.json
def index
#campers = #customer.campers
end
def list
query = params[:q].presence || ""
#campers = Camper.search(query, page: params[:page], per_page: 20, order: {created_at: :desc} )
end
# GET /campers/1
# GET /campers/1.js
def show
#appointments = #camper.appointments
respond_to do |format|
format.html
format.json
end
end
# GET /campers/new
def new
#customer = Customer.find(params[:customer_id])
#camper = #customer.campers.build
end
# GET /campers/1/edit
def edit
end
def page_name
"Campers"
end
# POST /campers
# POST /campers.json
def create
#camper = Camper.new(camper_params)
respond_to do |format|
if #camper.save
format.html { redirect_to camper_path(#camper), notice: 'Camper was successfully created.' }
format.json { render :show, status: :created, location: #camper }
else
format.html { render :new }
format.json { render json: #camper.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /campers/1
# PATCH/PUT /campers/1.json
def update
respond_to do |format|
if #camper.update(camper_params)
format.html { redirect_to camper_path(#camper), notice: 'Camper was successfully updated.' }
format.json { render :show, status: :ok, location: #camper }
else
format.html { render :edit }
format.json { render json: #camper.errors, status: :unprocessable_entity }
end
end
end
# DELETE /campers/1
# DELETE /campers/1.json
def destroy
#camper.destroy
respond_to do |format|
format.html { redirect_to root_path, notice: 'Camper was successfully deleted.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_camper
#camper = Camper.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def camper_params
params.require(:camper).permit(:order_id, :customer_id, :year, :manufacturer, :modelName, :camperClass, :vin, :mileage, :notes, :user_id)
end
end
Appointments Controller
class AppointmentsController < ApplicationController
before_action :set_appointment, only: [:show, :edit, :update, :destroy]
# GET /appointments
# GET /appointments.json
def index
#camper = Camper.find(params[:camper_id])
#appointments = #camper.appointments
end
# GET /appointments/1
# GET /appointments/1.json
def show
#orders = #appointment.orders
end
# GET /appointments/newå
def new
#camper = Camper.find(params[:camper_id])
#appointment = #camper.appointments.build
end
# GET /appointments/1/edit
def edit
end
# POST /appointments
# POST /appointments.json
def create
#appointment = Appointment.new(appointment_params)
respond_to do |format|
if #appointment.save
format.html { redirect_to appointment_path(#appointment), notice: 'Appointment was successfully created.' }
format.json { render :show, status: :created, location: #appointment }
else
format.html { render :new }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /appointments/1
# PATCH/PUT /appointments/1.json
def update
respond_to do |format|
if #appointment.update(appointment_params)
format.html { redirect_to #appointment, notice: 'Appointment was successfully updated.' }
format.json { render :show, status: :ok, location: #appointment }
else
format.html { render :edit }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /appointments/1
# DELETE /appointments/1.json
def destroy
#appointment.destroy
respond_to do |format|
format.html { redirect_to camper_appointments_path(#appointment), notice: 'Appointment was successfully deleted.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_appointment
#appointment = Appointment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def appointment_params
params.require(:appointment).permit(:customer_id, :camper_id, :order_id, :title, :description, :date_in, :date_out)
end
end
appointment_path only takes a single appointment argument. Remove the #camper argument:
appointment_path(#appointment)
building a shopping app but i don't want to show to listings of the same thing twice. I don't want it to show two listings for oranges. Instead I want it to show the quantity as 2.
I have changed the order_items_controller to show
#order_item = #order.order_items.find_or_initialize_by_product_id(params[:product_id])
#order_item.quantity += 1
get error undefined method `price' for nil:NilClass
tr>
<th>Order Total</th>
<td><%= print_price #order.total %></td> <- error
</tr>
<tr>
order_items.controller
class OrderItemsController < ApplicationController
before_action :set_order_item, only: [:show, :edit, :update, :destroy]
before_action :load_order, only: [:create]
# GET /order_items/1/edit
def edit
end
# POST /order_items
# POST /order_items.json
def create
#order_item = #order.order_items.find_or_initialize_by_product_id(params[:product_id])
respond_to do |format|
if #order_item.save
format.html { redirect_to #order, notice: 'Successfully Added Product To Cart.' }
format.json { render action: 'show', status: :created, location: #order_item }
else
format.html { render action: 'new' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /order_items/1
# PATCH/PUT /order_items/1.json
def update
respond_to do |format|
if #order_item.update(order_item_params)
format.html { redirect_to #order_item, notice: 'Order item was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /order_items/1
# DELETE /order_items/1.json
def destroy
#order_item.destroy
respond_to do |format|
format.html { redirect_to #order_item.order }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order_item
#order_item = OrderItem.find(params[:id])
end
def load_order
#order = Order.find_or_initialize_by_id(session[:order_id], status: "Unsubmitted")
if #order.new_record?
#order.save!
session[:order_id] = #order.id
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_item_params
params.require(:order_item).permit(:product_id, :order_id, :quantity)
end
end
orders.show.html
class OrderItemsController < ApplicationController
before_action :set_order_item, only: [:show, :edit, :update, :destroy]
before_action :load_order, only: [:create]
# GET /order_items/1/edit
def edit
end
# POST /order_items
# POST /order_items.json
def create
#order_item = #order.order_items.find_or_initialize_by_product_id(params[:product_id])
respond_to do |format|
if #order_item.save
format.html { redirect_to #order, notice: 'Successfully Added Product To Cart.' }
format.json { render action: 'show', status: :created, location: #order_item }
else
format.html { render action: 'new' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /order_items/1
# PATCH/PUT /order_items/1.json
def update
respond_to do |format|
if #order_item.update(order_item_params)
format.html { redirect_to #order_item, notice: 'Order item was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /order_items/1
# DELETE /order_items/1.json
def destroy
#order_item.destroy
respond_to do |format|
format.html { redirect_to #order_item.order }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order_item
#order_item = OrderItem.find(params[:id])
end
def load_order
#order = Order.find_or_initialize_by_id(session[:order_id], status: "Unsubmitted")
if #order.new_record?
#order.save!
session[:order_id] = #order.id
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_item_params
params.require(:order_item).permit(:product_id, :order_id, :quantity)
end
end
order.rb
class Order < ActiveRecord::Base
has_many :order_items, dependent: :destroy
def total
order_items.map(&:subtotal).sum
end
end
order_items.rb
class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
validates :order_id, :product_id, presence: true
def subtotal
quantity * product.price
end
end
I have also created a table to add quantity
class AddDefaultQuantityToOrderItems < ActiveRecord::Migration
def change
change_column :order_items, :quantity, :integer, default: 0
end
end
The problem might be in your order model. You need 'self' to reference the current Order object. Change it to this
def total
self.order_items.map(&:subtotal).sum
end
In your create action for the order controller you need
#order = Order.find(<however you get the order id>)
you are trying to call a method on #order but you are not passing a value in the controller for that item as far as I can tell