跳至内容 跳至搜索

Routing Concerns 允许您声明可重用在其他资源和路由中的通用路由。

concern :commentable do
  resources :comments
end

concern :image_attachable do
  resources :images, only: :index
end

这些 concerns 用于 Resources 路由

resources :messages, concerns: [:commentable, :image_attachable]

或在 scope 或 namespace 中

namespace :posts do
  concerns :commentable
end
方法
C

实例公共方法

concern(name, callable = nil, &block)

使用名称定义一个路由 concern。

Concerns 可以内联定义(使用块),或由另一个对象处理(将该对象作为第二个参数传递)。

如果提供了 concern 对象,它应该响应 call 方法,该方法将接收两个参数

* The current mapper
* A hash of options which the concern object may use

通过接受块参数,可以在块中定义的 concerns 中使用选项。因此,使用块,您可以简单地限制某些资源上可用的操作,并将标准的资源选项传递给 concern。

concern :commentable do |options|
  resources :comments, options
end

resources :posts, concerns: :commentable
resources :archived_posts do
  # Don't allow comments on archived posts
  concerns :commentable, only: [:index, :show]
end

或者,使用可调用对象,您可以实现更特定的于您的应用程序的功能,这些功能不适合放在路由文件中。

# purchasable.rb
class Purchasable
  def initialize(defaults = {})
    @defaults = defaults
  end

  def call(mapper, options = {})
    options = @defaults.merge(options)
    mapper.resources :purchases
    mapper.resources :receipts
    mapper.resources :returns if options[:returnable]
  end
end

# routes.rb
concern :purchasable, Purchasable.new(returnable: true)

resources :toys, concerns: :purchasable
resources :electronics, concerns: :purchasable
resources :pets do
  concerns :purchasable, returnable: false
end

任何路由助手都可以在 concern 内部使用。如果使用可调用对象,它们可以从传递给 callMapper 中访问。

# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2297
def concern(name, callable = nil, &block)
  callable ||= lambda { |mapper, options| mapper.instance_exec(options, &block) }
  @concerns[name] = callable
end

concerns(*args, **options)

使用命名的 concerns

resources :posts do
  concerns :commentable
end

Concerns 也适用于您想要使用的任何路由助手。

namespace :posts do
  concerns :commentable
end
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2313
def concerns(*args, **options)
  args.flatten.each do |name|
    if concern = @concerns[name]
      concern.call(self, options)
    else
      raise ArgumentError, "No concern named #{name} was found!"
    end
  end
end