Module: Padrino::Routing::ClassMethods

Defined in:
lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb

Overview

Class methods responsible for enhanced routing for controllers.

Instance Method Summary collapse

Instance Method Details

#add_filter(type, &block) ⇒ Object

Adds a filter hook to a request.



363
364
365
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 363

def  add_filter(type, &block)
  filters[type] << block
end

#after(*args, &block) ⇒ Object

Add an after filter hook

See Also:



356
357
358
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 356

def after(*args, &block)
  add_filter :after, &(args.empty? ? block : construct_filter(*args, &block))
end

#before(*args, &block) ⇒ Object

Add a before filter hook

See Also:



347
348
349
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 347

def before(*args, &block)
  add_filter :before, &(args.empty? ? block : construct_filter(*args, &block))
end

#compiled_routerObject

Compiles the routes including deferred routes.



463
464
465
466
467
468
469
470
471
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 463

def compiled_router
  if deferred_routes.empty?
    router
  else
    deferred_routes.each { |_, routes| routes.each { |(route, dest)| route.to(dest) } }
    @deferred_routes = nil
    router
  end
end

#construct_filter(*args, &block) ⇒ Object

Creates a filter to process before/after the matching route.

Examples:

We are be able to filter with String path

before('/') { 'only to :index' }
get(:index} { 'foo' } # => filter match only before this.
get(:main) { 'bar' }

is the same of

before(:index) { 'only to :index' }
get(:index} { 'foo' } # => filter match only before this.
get(:main) { 'bar' }

it works only for the given controller

controller :foo do
  before(:index) { 'only to for :foo_index' }
  get(:index} { 'foo' } # => filter match only before this.
  get(:main) { 'bar' }
end

controller :bar do
  before(:index) { 'only to for :bar_index' }
  get(:index} { 'foo' } # => filter match only before this.
  get(:main) { 'bar' }
end

if filters based on a symbol or regexp

before :index, /main/ do; ... end
# => match oly path that are  +/+ or contains +main+

filtering everything except an occurency

before :except => :index do; ...; end

you can also filter using a request param

before :agent => /IE/ do; ...; end
# => match +HTTP_USER_AGENT+ containing +IE+

Parameters:

  • args (Array)

See Also:



408
409
410
411
412
413
414
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 408

def construct_filter(*args, &block)
  options = args.last.is_a?(Hash) ? args.pop : {}
  except = options.key?(:except) && Array(options.delete(:except))
  raise("You cannot use except with other options specified") if except && (!args.empty? || !options.empty?)
  options = except.last.is_a?(Hash) ? except.pop : {} if except
  Filter.new(!except, @_controller, options, Array(except || args), &block)
end

#controller(*args) { ... } ⇒ Object Also known as: controllers

Method to organize our routes in a better way.

In a controller, before and after filters are scoped and don’t affect other controllers or the main app. In a controller, layouts are scoped and don’t affect other controllers or the main app.

Examples:

controller :admin do
  get :index do; ...; end
  get :show, :with => :id  do; ...; end
end

url(:admin_index) # => "/admin"
url(:admin_show, :id => 1) # "/admin/show/1"

Using named routes follow the sinatra way:

controller "/admin" do
  get "/index" do; ...; end
  get "/show/:id" do; ...; end
end

Supply :provides to all controller routes:

controller :provides => [:html, :xml, :json] do
  get :index do; "respond to html, xml and json"; end
  post :index do; "respond to html, xml and json"; end
  get :foo do; "respond to html, xml and json"; end
end

Specify parent resources in padrino with the :parent option on the controller:

controllers :product, :parent => :user do
  get :index do
    # url is generated as "/user/#{params[:user_id]}/product"
    # url_for(:product, :index, :user_id => 5) => "/user/5/product"
  end
  get :show, :with => :id do
    # url is generated as "/user/#{params[:user_id]}/product/show/#{params[:id]}"
    # url_for(:product, :show, :user_id => 5, :id => 10) => "/user/5/product/show/10"
  end
end

Specify conditions to run for all routes:

controller :conditions => {:protect => true} do
  def self.protect(protected)
    condition do
      halt 403, "No secrets for you!" unless params[:key] == "s3cr3t"
    end if protected
  end

  # This route will only return "secret stuff" if the user goes to
  # `/private?key=s3cr3t`.
  get("/private") { "secret stuff" }

  # And this one, too!
  get("/also-private") { "secret stuff" }

  # But you can override the conditions for each route as needed.
  # This route will be publicly accessible without providing the
  # secret key.
  get :index, :protect => false do
    "Welcome!"
  end
end

Supply default values:

controller :lang => :de do
  get :index, :map => "/:lang" do; "params[:lang] == :de"; end
end
controller :posts do
  layout :post
  before { foo }
  after  { bar }
end

Parameters:

  • args (Array)

    Controller arguments.

Yields:

  • The given block will be used to define the routes within the Controller.



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 308

def controller(*args, &block)
  if block_given?
    options = args.extract_options!

    # Controller defaults
    @_controller, original_controller = args,                        @_controller
    @_parents,    original_parent     = options.delete(:parent),     @_parents
    @_provides,   original_provides   = options.delete(:provides),   @_provides
    @_use_format, original_use_format = options.delete(:use_format), @_use_format
    @_cache,      original_cache      = options.delete(:cache),      @_cache
    @_map,        original_map        = options.delete(:map),        @_map
    @_conditions, original_conditions = options.delete(:conditions), @_conditions
    @_defaults,   original_defaults   = options,                     @_defaults

    # Application defaults
    @filters,     original_filters    = { :before => @filters[:before].dup, :after => @filters[:after].dup }, @filters
    @layout,      original_layout     = nil, @layout

    instance_eval(&block)

    # Application defaults
    @filters        = original_filters
    @layout         = original_layout

    # Controller defaults
    @_controller, @_parents,  @_cache = original_controller, original_parent,   original_cache
    @_defaults,   @_provides, @_map   = original_defaults,   original_provides, original_map
    @_conditions, @_use_format        = original_conditions, original_use_format
  else
    include(*args) if extensions.any?
  end
end

#deferred_routesObject

Returns all routes that were deferred based on their priority.



474
475
476
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 474

def deferred_routes
  @deferred_routes ||= Hash[ROUTE_PRIORITY.values.sort.map{|p| [p, []]}]
end

#get(path, *args, &block) ⇒ Object



548
549
550
551
552
553
554
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 548

def get(path, *args, &block) # @private
  conditions = @conditions.dup
  route('GET', path, *args, &block)

  @conditions = conditions
  route('HEAD', path, *args, &block)
end

#parent(name, options = {}) ⇒ Object

Provides many parents with shallowing.

Examples:

controllers :product do
  parent :shop, :optional => true, :map => "/my/stand"
  parent :category, :optional => true
  get :show, :with => :id do
    # generated urls:
    #   "/product/show/#{params[:id]}"
    #   "/my/stand/#{params[:shop_id]}/product/show/#{params[:id]}"
    #   "/my/stand/#{params[:shop_id]}/category/#{params[:category_id]}/product/show/#{params[:id]}"
    # url_for(:product, :show, :id => 10) => "/product/show/10"
    # url_for(:product, :show, :shop_id => 5, :id => 10) => "/my/stand/5/product/show/10"
    # url_for(:product, :show, :shop_id => 5, :category_id => 1, :id => 10) => "/my/stand/5/category/1/product/show/10"
  end
end

Parameters:

  • name (Symbol)

    The parent name.

  • options (Hash) (defaults to: {})

    Additional options.



440
441
442
443
444
445
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 440

def parent(name, options={})
  defaults = { :optional => false, :map => name.to_s }
  options = defaults.merge(options)
  @_parents = Array(@_parents) unless @_parents.is_a?(Array)
  @_parents << Parent.new(name, options)
end

#recognize_path(path) ⇒ Symbol, Hash

Recognize a given path

Examples:

Giving a controller like:

controller :foo do
  get :bar, :map => 'foo-bar-:id'; ...; end
end

You should be able to reverse:

MyApp.url(:foo_bar, :id => :mine)
# => /foo-bar-mine

Into this:

MyApp.recognize_path('foo-bar-mine')
# => [:foo_bar, :id => :mine]

Parameters:

  • path (String)

    Path+Query to parse

Returns:

  • (Symbol, Hash)

    Returns controller and query params.



508
509
510
511
512
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 508

def recognize_path(path)
  responses = @router.recognize(Rack::MockRequest.env_for(path))
  responses = responses[0] if responses[0].is_a?(Array)
  [responses[0].path.route.name, responses[0].params]
end

#reset_router!Object

Resets the http router and all deferred routes.



481
482
483
484
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 481

def reset_router!
  @deferred_routes = nil
  router.reset!
end

#routerObject Also known as: urls

Using HttpRouter, for features and configurations.

Examples:

router.add('/greedy/:greed')
router.recognize('/simple')

See Also:



456
457
458
459
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 456

def router
  @router ||= HttpRouter.new
  block_given? ? yield(@router) : @router
end

#url(*args) ⇒ Object Also known as: url_for

Instance method for url generation.

Examples:

url(:show, :id => 1)
url(:show, :name => 'test', :id => 24)
url(:show, 1)
url(:controller_name, :show, :id => 21)
url(:controller_show, :id => 29)


524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/application/routing.rb', line 524

def url(*args)
  params = args.extract_options!  # parameters is hash at end
  names, params_array = args.partition{|a| a.is_a?(Symbol)}
  name = names.join("_").to_sym    # route name is concatenated with underscores
  if params.is_a?(Hash)
    params[:format] = params[:format].to_s unless params[:format].nil?
    params = value_to_param(params)
  end
  url =
    if params_array.empty?
      compiled_router.path(name, params)
    else
      compiled_router.path(name, *(params_array << params))
    end
  url[0,0] = conform_uri(uri_root) if defined?(uri_root)
  url[0,0] = conform_uri(ENV['RACK_BASE_URI']) if ENV['RACK_BASE_URI']
  url = "/" if url.blank?
  url
rescue HttpRouter::InvalidRouteException
  route_error = "route mapping for url(#{name.inspect}) could not be found!"
  raise Padrino::Routing::UnrecognizedException.new(route_error)
end