约束

你可以使用约束过滤可用的路径。

有几种方法可以使用约束,包括:

例如,基于请求的约束仅允许特定 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