約束

你可以使用約束過濾可用的路徑。

有幾種方法可以使用約束,包括:

例如,基於請求的約束僅允許特定 IP 地址訪問路由:

constraints(ip: /127\.0\.0\.1$/) do
  get 'route', to: "controller#action"
end

檢視其他類似的示例 ActionDispatch::Routing::Mapper::Scoping

如果你想做一些更復雜的事情,你可以使用更高階的約束並建立一個類來包裝邏輯:

# lib/api_version_constraint.rb
class ApiVersionConstraint
  def initialize(version:, default:)
    @version = version
    @default = default
  end

  def version_header
    "application/vnd.my-app.v#{@version}"
  end

  def matches?(request)
    @default || request.headers["Accept"].include?(version_header)
  end
end

# config/routes.rb
require "api_version_constraint"

Rails.application.routes.draw do
  namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
    resources :users # Will route to app/controllers/v1/users_controller.rb
  end

  namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
    resources :users # Will route to app/controllers/v2/users_controller.rb
  end
end

一個表單,幾個提交按鈕

你還可以使用表單的提交標記的值作為約束來路由到不同的操作。如果你有一個包含多個提交按鈕的表單(例如預覽提交),你可以直接在 routes.rb 中捕獲此約束,而不是編寫 javascript 來更改表單目標 URL。例如,使用 commit_param_routing gem,你可以利用 rails submit_tag

Rails submit_tag 第一個引數允許你更改表單提交引數的值

# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
    <!-- Big form here -->
  <%= submit_tag "Preview" %>
  <%= submit_tag "Submit" %>
  # => <input name="commit" type="submit" value="Preview" />
  # => <input name="commit" type="submit" value="Submit" />
  ...
<% end %>

# config/routes.rb
resources :orders do
  # Both routes below describe the same POST URL, but route to different actions 
  post 'mass_order', on: :collection, as: 'mass_order',
    constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
  post 'mass_order', on: :collection,
    constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
  # Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
  # CommitParamRouting is just a class like ApiVersionContraint
end