Class: Merb::Router::Route

Inherits:
Object show all
Defined in:
lib/merb-core/dispatch/router/route.rb

Overview

This entire class is private and should never be accessed outside of Merb::Router and Behavior

Defined Under Namespace

Classes: Generator

Constant Summary collapse

SEGMENT_REGEXP =

:nodoc:

/(:([a-z](_?[a-z0-9])*))/
OPTIONAL_SEGMENT_REGEX =
/^.*?([\(\)])/i
SEGMENT_REGEXP_WITH_BRACKETS =
/(:[a-z_]+)(\[(\d+)\])?/
JUST_BRACKETS =
/\[(\d+)\]/
SEGMENT_CHARACTERS =
"[^\/.,;?]".freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conditions, params, deferred_procs, options = {}) ⇒ Route

:api: private



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/merb-core/dispatch/router/route.rb', line 21

def initialize(conditions, params, deferred_procs, options = {})
  @conditions, @params = conditions, params

  if options[:redirects]
    @redirects         = true
    @redirect_status   = @params[:status]
    @redirect_url      = @params[:url]
    @defaults          = {}
  else
    @generatable       = true
    @defaults          = options[:defaults] || {}
  end
  
  @identifiers       = options[:identifiers]
  @deferred_procs    = deferred_procs
  @segments          = []
  @symbol_conditions = {}
  @placeholders      = {}
  compile
end

Instance Attribute Details

#conditionsObject (readonly)

:api: private



14
15
16
# File 'lib/merb-core/dispatch/router/route.rb', line 14

def conditions
  @conditions
end

#fixationObject

:api: private



18
19
20
# File 'lib/merb-core/dispatch/router/route.rb', line 18

def fixation
  @fixation
end

#indexObject (readonly)

:api: private



16
17
18
# File 'lib/merb-core/dispatch/router/route.rb', line 16

def index
  @index
end

#nameObject

:api: private



16
17
18
# File 'lib/merb-core/dispatch/router/route.rb', line 16

def name
  @name
end

#paramsObject (readonly)

:api: private



14
15
16
# File 'lib/merb-core/dispatch/router/route.rb', line 14

def params
  @params
end

#resource_identifiersObject

:api: private



18
19
20
# File 'lib/merb-core/dispatch/router/route.rb', line 18

def resource_identifiers
  @resource_identifiers
end

#segmentsObject (readonly)

:api: private



14
15
16
# File 'lib/merb-core/dispatch/router/route.rb', line 14

def segments
  @segments
end

#variablesObject (readonly)

:api: private



16
17
18
# File 'lib/merb-core/dispatch/router/route.rb', line 16

def variables
  @variables
end

Instance Method Details

#allow_fixation?Boolean

:api: private

Returns:

  • (Boolean)


53
54
55
# File 'lib/merb-core/dispatch/router/route.rb', line 53

def allow_fixation?
  @fixation
end

#compiled_statement(first) ⇒ Object

Returns the if statement and return value for for the main Router.match compiled method.

:api: private



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/merb-core/dispatch/router/route.rb', line 201

def compiled_statement(first)
  els_if = first ? '  if ' : '  elsif '

  code = ""
  code << els_if << condition_statements.join(" && ") << "\n"
  
  # First, we need to always return the value of the
  # deferred block if it explicitly matched the route
  if @redirects
    code << "    return [#{@index.inspect}, block_result] if request.matched?" << "\n" if @deferred_procs.any?
    code << "    [#{@index.inspect}, Merb::Rack::Helpers.redirect(#{@redirect_url.inspect}, :status => #{@redirect_status.inspect})]" << "\n"
  elsif @deferred_procs.any?
    code << "    [#{@index.inspect}, block_result]" << "\n"
  else
    code << "    [#{@index.inspect}, #{params_as_string}]" << "\n"
  end
end

#generatable?Boolean

:api: private

Returns:

  • (Boolean)


48
49
50
# File 'lib/merb-core/dispatch/router/route.rb', line 48

def generatable?
  @generatable && !regexp?
end

#generate(args = [], defaults = {}, resource = false) ⇒ Object

Generates the URL for the route given the passed arguments. The method will first match the anonymous parameters to route params and will convert all the parameters according to the specifed object identifiers.

Then the named parameters are passed to a compiled generation proc.

Parameters

args<Array>

The arguments passed to the public #url method with the name of the route removed. This is an array of the anonymous parameters followed by a hash containing the named parameters.

defaults<Hash>

A hash of parameters to use to generate the route if there are any missing required parameters. This is usually the parameters for the current request

Returns

String

The generated URL.

:api: private



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/merb-core/dispatch/router/route.rb', line 120

def generate(args = [], defaults = {}, resource = false)
  unless generatable?
    raise GenerationError, "Cannot generate regexp Routes" if regexp?
    raise GenerationError, "Cannot generate this route"
  end
  
  params = extract_options_from_args!(args) || { }
  # Duplicating to avoid mutating arguments
  params = params ? params.dup : {}
  
  params.each do |k, v|
    params[k] = identify(v, k)
  end
  
  # Support for anonymous params
  unless args.empty?
    # First, let's determine which variables are missing
    variables = (resource ? @resource_identifiers : @variables) - params.keys
    
    args.each do |param|
      raise GenerationError, "The route has #{@variables.length} variables: #{@variables.inspect}" if variables.empty?
      
      if identifier = identifier_for(param) and identifier.is_a?(Array)
        identifier.each { |ident| params[variables.shift] = param.send(ident) }
      else
        params[variables.shift] ||= identify(param)
      end
    end
  end
  
  uri = @generator[params, defaults] or raise GenerationError, "Named route #{name} could not be generated with #{params.inspect}"
  uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
  uri
end

#identifier_for(obj) ⇒ Object

Returns the identifier for the passed object. Built in core ruby classes are always identified with to_s. The method will return nil in that case (since to_s is the default for objects that do not have identifiers.)

:api: private



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/merb-core/dispatch/router/route.rb', line 185

def identifier_for(obj)
  return if obj.is_a?(String)    || obj.is_a?(Symbol)     || obj.is_a?(Numeric)  ||
            obj.is_a?(TrueClass) || obj.is_a?(FalseClass) || obj.is_a?(NilClass) ||
            obj.is_a?(Array)     || obj.instance_of?(Hash)
  
  @identifiers.each do |klass, identifier|
    return identifier if obj.is_a?(klass)
  end
  
  return nil
end

#identify(obj, param_key = nil) ⇒ Object

Identifies the object according to the identifiers set while building the routes. Identifying an object means picking an instance method to call on the object that will return a string representation of the object for the route being generated. If the identifier is an array, then a param_key must be present and match one of the elements of the identifier array.

param_keys that end in _id are treated slightly differently in order to get nested resources to work correctly.

:api: private



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/merb-core/dispatch/router/route.rb', line 166

def identify(obj, param_key = nil)
  identifier = identifier_for(obj)
  if identifier.is_a?(Array)
    # First check if the param_key exists as an identifier
    return obj.send(param_key) if identifier.include?(param_key)
    # If the param_key ends in _id, just return the object id
    return obj.id if "#{param_key}" =~ /_id$/
    # Otherwise, raise an error
    raise GenerationError, "The object #{obj.inspect} cannot be identified with #{identifier.inspect} for #{param_key}"
  else
    identifier ? obj.send(identifier) : obj
  end
end

#regexp?Boolean

:api: private

Returns:

  • (Boolean)


43
44
45
# File 'lib/merb-core/dispatch/router/route.rb', line 43

def regexp?
  @regexp
end

#registerObject

:api: private



69
70
71
72
73
# File 'lib/merb-core/dispatch/router/route.rb', line 69

def register
  @index = Merb::Router.routes.size
  Merb::Router.routes << self
  self
end

#register_at(index) ⇒ Object

Inserts self to Merb::Router.routes at the specified index. :api: private



77
78
79
80
81
# File 'lib/merb-core/dispatch/router/route.rb', line 77

def register_at(index)
  @index = index
  Merb::Router.routes.insert(index, self)
  self
end

#resource=(key) ⇒ Object

Sets the route as a resource route with the given key as the lookup key. :api: private



86
87
88
89
# File 'lib/merb-core/dispatch/router/route.rb', line 86

def resource=(key)
  Router.resource_routes[key] = self
  key
end

#to_sObject Also known as: inspect

:api: private



58
59
60
61
62
# File 'lib/merb-core/dispatch/router/route.rb', line 58

def to_s
  regexp? ?
    "/#{conditions[:path].source}/" :
    segment_level_to_s(segments)
end