From 05136e5c0b3d7b841bdec53847879321309604d3 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Sun, 26 Aug 2012 15:37:23 -0400 Subject: Make enhanced routing Concerns more tell-don't-ask --- actionpack/lib/action_dispatch/routing/mapper.rb | 80 ++++++++++++++++-------- 1 file changed, 55 insertions(+), 25 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 8573f4d80b..ddb34a2394 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1585,7 +1585,7 @@ module ActionDispatch end end - # Routing Concerns allows you to declare common routes that can be reused + # Routing Concerns allow you to declare common routes that can be reused # inside others resources and routes. # # concern :commentable do @@ -1606,32 +1606,65 @@ module ActionDispatch # concerns :commentable # end module Concerns - # Define a routing concern using a name. If a second parameter is - # supplied, it should respond to call, which will receive the mapper - # as a parameter, allowing for customized behavior based on the current - # scope. + # Define a routing concern using a name. # - # concern :commentable do - # resources :comments + # Concerns may be defined inline, using a block, or handled by + # another object, by passing that object as the second parameter. + # + # The concern object, if supplied, should respond to call, + # which will receive two parameters: + # + # * The current mapper + # * A hash of options which the concern object may use + # + # Options may also be used by concerns defined in a block by accepting + # a block parameter. So, using a block, you might do something as + # simple as limit the actions available on certain resources, passing + # standard resource options through the 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 # - # # - or - + # Or, using a callable object, you might implement something more + # specific to your application, which would be out of place in your + # routes file. # - # class Commentable - # def self.call(mapper) - # if mapper.current_scope[:controller] == 'videos' - # mapper.resources :video_comments, as: :comments - # else - # mapper.resources :comments - # 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 # - # concern :commentable, Commentable + # # routes.rb + # concern :purchasable, Purchasable.new(returnable: true) + # + # resources :toys, concerns: :purchasable + # resources :electronics, concerns: :purchasable + # resources :pets do + # concerns :purchasable, returnable: false + # end # - # Any routing helpers can be used inside a concern. + # Any routing helpers can be used inside a concern. If using a + # callable, they're accessible from the Mapper that's passed to + # call. def concern(name, callable = nil, &block) - @concerns[name] = callable || lambda { |m| m.instance_eval(&block) } + callable ||= lambda { |mapper, options| mapper.instance_exec(options, &block) } + @concerns[name] = callable end # Use the named concerns @@ -1645,10 +1678,11 @@ module ActionDispatch # namespace :posts do # concerns :commentable # end - def concerns(*names) - names.flatten.each do |name| + def concerns(*args) + options = args.extract_options! + args.flatten.each do |name| if concern = @concerns[name] - concern.call(self) + concern.call(self, options) else raise ArgumentError, "No concern named #{name} was found!" end @@ -1662,10 +1696,6 @@ module ActionDispatch @concerns = {} end - def current_scope - @scope - end - include Base include HttpHelpers include Redirection -- cgit v1.2.3