Neil
Neil

Reputation: 141

undefined method `order_url'

trying to setup a page so users can place an order when they sign in..

if you type in /listings/27/orders/new this will go to a new order form so you can order item 27. But when i fill in the address details and create an order I get error..NoMethodError in OrdersController#create..undefined method `order_url' for #

OrdersController#create

class OrdersController < ApplicationController
  before_action :set_order, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!

  # 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
    @listing = Listing.find(params[:listing_id])
  end

  # GET /orders/1/edit
  def edit
  end

  # POST /orders
  # POST /orders.json
  def create
    @order = Order.new(order_params)
    @listing = Listing.find(params[:listing_id])
    @seller = @listing.user


    @order.listing_id = @listing.id
    @order.buyer_id = current_user.id
    @order.seller_id = @seller.id


    respond_to do |format|
      if @order.save
         # ERROR on the following line!!
        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)
        format.html { redirect_to @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 orders_url }
      format.json { head :no_content }
    end
  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(:delivery_address, :delivery_city, :delivery_state)
    end
end

listing.db

class Listing < ActiveRecord::Base
    if Rails.env.development?
        has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "photo.jpg"
    else
    has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "photo.jpg",
                      :storage => :dropbox,
                      :dropbox_credentials => Rails.root.join("config/dropbox.yml"),
                      :path => ":style/id_:filename"
    end
    validates :name, :description, :price, presence: true
    validates :price, numericality: { greater_than: 0 }
    validates_attachment_presence :image

    belongs_to :user
    has_many  :orders
end

order.rb

class Order < ActiveRecord::Base
    validates :delivery_address, :delivery_city, :delivery_state, presence: true

    belongs_to :listing
    belongs_to :buyer, class_name: "User"
    belongs_to :seller, class_name: "User"
end

user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

   validates :name, presence: true

   has_many :listings, dependT.nt: :destroy
   has_many :sales, class_name: "Order", foreign_key: "seller_id"
   has_many :purchases, class_name: "Order", foreign_key: "buyer_id"
end

rake routes

devise_for :users
    resources :listings do
         resources :orders
  end


  get "pages/about"
  get "pages/contact"
  get 'seller' => "listings#seller"


  root 'listings#index'

Upvotes: 0

Views: 382

Answers (3)

lucke84
lucke84

Reputation: 4636

I believe you're redirecting to a variable, while you should redirect to a URL present in you routes file.

I think it should be:

# ...

respond_to do |format|
  if @order.save
    format.html { listing_order_url(@listing, @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

Upvotes: 0

Kirti Thorat
Kirti Thorat

Reputation: 53038

As per the nested routes,

devise_for :users
    resources :listings do
         resources :orders
end

order_url doesn't exist, redirecting to @order will make rails look for a path order_url. Do rake routes and check the available paths(look at the prefix column).

Use

redirect_to listing_order_url(@listing,@order)

instead of

redirect_to @order

in both create and update actions of OrdersController.

Also, update destroy action as below

  def destroy
    @order.destroy
    respond_to do |format|
      format.html { redirect_to listing_orders_url(@order.listing) } ## orders_url doesn't exist, use listing_orders_url
      format.json { head :no_content }
    end
  end

Upvotes: 1

raviolicode
raviolicode

Reputation: 2175

You are using nested resources. You should change the redirect to use a nested resource url, in this case to:

redirect_to listing_order_url(@listing, @order), notice: 'Your order has been created'

According to Rails Guides, if it's a link_to you could use this other format:

link_to 'Order Details', [@listing, @order]

Upvotes: 0

Related Questions