Rails button_to No route matches {:action=>“comple

2019-06-05 20:21发布

问题:

Please help i have tried my best. I really need your help.

So im trying to make a mark order as complete. Now it all works up to the button to mark order as complete. I ran a migration to add.

class AddCompleteToOrder < ActiveRecord::Migration
  def change
    add_column :orders, :complete, :boolean, default: false
  end
end

Then i added a method the order.rb of

def complete!
  update(complete: true)
end

Then routes.rb

resources :orders do
  post "complete", to: "orders#complete", on: :member
end

Then this is the button

= button_to "Mark as complete", { action: "complete", id: @order.id }

But i dont have a @order.id but a order does have a @order.name so i changed it to

= button_to "Mark as complete", { action: "complete", name: @order.name }

But then i get the error:

ActionController::UrlGenerationError in Dashboard#dadmin Showing /Users/jacksharville/Desktop/dancer/app/views/dashboard/dadmin.html.haml where line #87 raised:

No route matches {:action=>"complete", :controller=>"dashboard", :name=>"Order"}

Extracted source (around line #87): 85 86 87

= link_to "Back to Dashboard", :back, :class => 'btn-danger btn'

= button_to "Mark as complete", { action: "complete", name: @order.name }

So clearly im doing the routes.rb wrong but i cant fix it. Please help. Any help greatly appreciated.

routes.rb (full file)

Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  get 'home/index'
  root 'home#index'
  #pages
  get '/why' => 'pages#why'
  get '/trak' => 'pages#trak'
  get '/contact' => 'pages#contact'
  get '/mydms' => 'pages#mydms'
  get '/air' => 'pages#air'
  get '/ocean' => 'pages#ocean'
  get '/road' => 'pages#road'
  get '/courier' => 'pages#courier'
  get 'fulfilment' => 'pages#fulfilment'
  get 'express' => 'pages#express'

  resources :dashboard
  get 'dadmin' => 'dashboard#dadmin'
  get 'myorders' => 'dashboard#myorders'
  get 'label' => 'dashboard#label'
  resources "contacts", only: [:new, :create]

  devise_for :users
  as :user do
    get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
    put 'users' => 'devise/registrations#update', :as => 'user_registration'
  end

  resources "orders"
  get "/confirm" => "confirmations#show"
  get 'dconfirmation' => 'orders#confirmation'

  resources :orders do
    post "complete", to: "orders#complete", on: :member
  end
end

orders_controller.rb

class OrdersController < ApplicationController
  before_filter :authenticate_user!
  def new
    @order = Order.new
  end

  def create
    @order = current_user.orders.new(order_params)
    @order.email = current_user.email
    @order.name = current_user.name
    @order.address_line_1 = current_user.address_line_1
    @order.address_line_2 = current_user.address_line_2
    @order.postcode = current_user.postcode
    @order.city = current_user.city
    @order.country = current_user.country
    if @order.save
      redirect_to dconfirmation_path
    end
  end

  def order_params
    params.require(:order).
      permit(
        :email,
        :delivery_name,
        :company_name,
        :delivery_address1,
        :delivery_address2,
        :delivery_address3,
        :delivery_city,
        :delivery_postcode,
        :delivery_country,
        :phone,
        :package_contents,
        :description_content,
        :restricted_items,
        :terms_conditions,
        :insurance,
        :contents_value,
        :cf_reference,
        :reference_number
        )
  end
  def show
    @user = User.find(params[:id])
  end

  def confirmation
  end

  def complete!
    order = Order.find(params[:id])
    order.complete!
    # handle response
  end

end

dashboard_controller.rb

class DashboardController < ApplicationController

  before_filter :authenticate_user!

  def index
  end

  def admindashboard
    (current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
  end

  def adminuser
    (current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
  end

  def dadmin
    (current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
    # @order = Order.all
    @order = Order.order("name").page(params[:page]).per(1)
  end

  def myorders
    @order = current_user.orders.order("name").page(params[:page]).per(1)
  end

  def show
    @user = User.find(params[:id])
  end

  def label
    @order = current_user.orders.order("name").page(params[:page]).per(1)
  end

  def complete!
    order = Order.find(params[:id])
    order.complete!
    # handle response
  end
end

回答1:

You can specify this additional option in the button_to tag :controller => "order", but the proper way to use button_to tag is to not create a separate hash for options. Instead use it as a button_to("Mark as complete", controller: "order", action: "complete", name: @order.name)



回答2:

try this

  button_to "Mark as complete", { controller: "orders", action: "complete", name: @order.name },  {method: :post}


回答3:

This link can help: Routing Error - No route matches when using button_to with custom action

rake routes give me:

complete_order POST   /order/:id/complete(.:format) orders#complete


回答4:

You need to move the complete action from DashboardsController to OrdersController, which is where it is defined in the routes file.

Also, you can probably use:

= button_to "Mark as complete", complete_order_path(@order)

The controller action is looking for params[:order_id] so it can find the right order. I am not sure how orders are defined in your view, but you will need to pass an order object to the path.

If by any chance you defined a to_param method in Order class, which defines order's name rather than id as params, you will need to update the complete action to look for an order by name.

But my guess is that it is the default id. So passing the order object to the path should work.