Rails路由变量

Bra*_*sen 2 ruby routing ruby-on-rails

订单可以有很多州.我想为那些创建命名路由.我需要将状态作为参数传递给控制器​​.这是我的想法,但它显然不起作用.

match "order/:state/:id" => "orders#%{state}", as: "%{state}"
Run Code Online (Sandbox Code Playgroud)

所以我希望order/address/17路由到订单#address,其中:state和:id作为params传入.同样,订单/ shipping/17将路由到订单#shipping,再次:state和:id将被传入.

这是控制器.

class OrdersController < ApplicationController

  before_filter :load_order, only: [:address, :shipping, :confirmation, :receipt]
  before_filter :validate_state, only: [:address, :shipping, :confirmation, :receipt]


  def address
    @order.build_billing_address unless @order.billing_address
    @order.build_shipping_address unless @order.shipping_address
  end


  def shipping
    @shipping_rates = @order.calculate_shipping_rates
  end


  def confirmation

  end


  def receipt

  end

  private 

  def load_order
    @order = Order.find(params[:id])
  end

  # Check to see if the user is on the correct action
  def validate_state
    if params[:state]
      unless params[:state] == @order.state
        redirect_to eval("#{@order.state}_path(:#{@order.state},#{@order.id})")
        return
      end
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

以下是我们最终的结果:

的routes.rb

%w(address shipping confirmation receipt).each do |state|
    match "order/#{state}/:id", :to => "orders##{state}", :as => state, :state => state
end
Run Code Online (Sandbox Code Playgroud)

orders_controller.rb

def validate_state
    if params[:state]
      unless params[:state] == @order.state
        redirect_to(eval("#{@order.state}_path(@order)"))
        return
      end
    end
  end
Run Code Online (Sandbox Code Playgroud)

Chr*_*ald 7

你是不是要能够与那种语法创建动态命名的路线,但你基本上只是使用:state:action.如果更换:state:action和手动指定控制器,它会工作.显然,您将不得不更改代码params[:action]而不是params[:state](或在before_filter中映射该变量),但除此之外它应该可以正常工作.

match "order/:action/:id", :controller => "orders"
Run Code Online (Sandbox Code Playgroud)

请注意,如果订单具有类似create或的RESTful资源映射delete,则此路由将允许对它们进行GET请求,这将是不好的; 您可能只想为要完成的每个操作添加显式路由.这也可以让你获得params[:state]:

%w(address shipping).each do |state|
  match "order/#{state}/:id", :to => "orders##{state}", :as => state, :state => state
end
Run Code Online (Sandbox Code Playgroud)