开发者

Rails Routing Variables

Orders can have many states. I would like to create named routes for those. I need the state to be passed in to the controller as a param. Here is what I was thinking, but it obviously does not work.

match "order/:state/:id" => "orders#%{state}", as: "%{state}"

So I would like order/address/17 to route to orders#address, with :state and :id being passed in as params. Likewise, order/shipping/17 would route to orders#shipping, again :state and :id would be passed in.

Here is the controller.

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

Here is what we ended up going with:

routes.rb

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

orders_controller.rb

def validate_state
    if params[:state]
      unless params[:state] == @order.state
        redirect_to(eval("#{@order.state}_path(@order)"))
        return
      end
    end
 开发者_JS百科 end


You aren't going to be able to create dynamic named routes with that sort of syntax, but you're basically just using :state as the :action. If you replace :state with :action and specify the controller manually, it'll work. Obviously, you will have to change your code to look at params[:action] rather than params[:state] (or map that variable in a before_filter), but beyond that it should work fine.

match "order/:action/:id", :controller => "orders"

Be aware that if orders has RESTful resource mappings like create or delete, this route would allow GET requests to them, which would be bad; you may just want to add explicit routes for each action you want to complete. This will let you get params[:state], as well:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜