Class: Usher
- Inherits:
-
Object
- Object
- Usher
- Defined in:
- lib/usher/interface.rb,
lib/usher.rb,
lib/usher/node.rb,
lib/usher/util.rb,
lib/usher/route.rb,
lib/usher/grapher.rb,
lib/usher/splitter.rb,
lib/usher/exceptions.rb,
lib/usher/route/path.rb,
lib/usher/route/util.rb,
lib/usher/util/parser.rb,
lib/usher/util/generate.rb,
lib/usher/route/variable.rb,
lib/usher/route/request_method.rb,
lib/usher/interface/merb_interface.rb,
lib/usher/interface/rack_interface.rb,
lib/usher/interface/text_interface.rb,
lib/usher/interface/email_interface.rb,
lib/usher/interface/rails3_interface.rb,
lib/usher/interface/rails2_2_interface.rb,
lib/usher/interface/rails2_3_interface.rb,
lib/usher/interface/rack_interface/route.rb,
lib/usher/interface/rails2_2_interface/mapper.rb
Overview
TODO: refactoring: I suggest to use usher/interfaces/rack.rb instead of usher/interface/rack_interface.rb, it will enable me to simplify this code
Defined Under Namespace
Modules: Interface, Util Classes: Grapher, MissingParameterException, Node, Route, Splitter, UnrecognizedException, ValidationException
Instance Attribute Summary collapse
-
#delimiter_chars ⇒ Object
readonly
Returns the value of attribute delimiter_chars.
-
#delimiters ⇒ Object
readonly
Returns the value of attribute delimiters.
-
#delimiters_regex ⇒ Object
readonly
Returns the value of attribute delimiters_regex.
-
#generator ⇒ Object
readonly
Returns the value of attribute generator.
-
#grapher ⇒ Object
readonly
Returns the value of attribute grapher.
-
#named_routes ⇒ Object
readonly
Returns the value of attribute named_routes.
-
#parent_route ⇒ Object
Returns the value of attribute parent_route.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#routes ⇒ Object
readonly
Returns the value of attribute routes.
-
#splitter ⇒ Object
readonly
Returns the value of attribute splitter.
Instance Method Summary collapse
-
#add_named_route(name, path, options = nil) ⇒ Object
Adds a route referencable by
name
. -
#add_route(path, options = nil) ⇒ Object
Creates a route from
path
andoptions
. - #can_generate? ⇒ Boolean
-
#delete_named_route(name, path, options = nil) ⇒ Object
Deletes a route referencable by
name
. -
#delete_route(path, options = nil) ⇒ Object
Deletes a route.
- #dup ⇒ Object
-
#empty? ⇒ Boolean
Returns whether the route set is empty.
-
#initialize(options = nil) ⇒ Usher
constructor
Creates a route set, with options.
-
#name(name, route) ⇒ Object
Attaches a
route
to aname
. - #parser ⇒ Object
-
#path_for_options(options) ⇒ Object
Recognizes a set of
parameters
and gets the closest matching Usher::Route::Path ornil
if no route exists. -
#recognize(request, path = request.path) ⇒ Object
Recognizes a
request
and returnsnil
or an Usher::Node::Response, which is a struct containing a Usher::Route::Path and an array of arrays containing the extracted parameters. -
#recognize_path(path) ⇒ Object
Recognizes a
path
and returnsnil
or an Usher::Node::Response, which is a struct containing a Usher::Route::Path and an array of arrays containing the extracted parameters. -
#reset! ⇒ Object
(also: #clear!)
Resets the route set back to its initial state.
- #route_count ⇒ Object
Constructor Details
#initialize(options = nil) ⇒ Usher
Creates a route set, with options
:delimiters
: Array of Strings. (default ['/', '.']
). Delimiters used in path separation. Array must be single character strings.
:valid_regex
: String. (default '[0-9A-Za-z\$\-_+!*\',]+'
). String that can be interpolated into regex to match valid character sequences within path.
:request_methods
: Array of Symbols. (default [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
) Array of methods called against the request object for the purposes of matching route requirements.
52 53 54 55 56 57 58 |
# File 'lib/usher.rb', line 52 def initialize( = nil) self.generator = && .delete(:generator) self.delimiters = && .delete(:delimiters) || ['/', '.'] self.valid_regex = && .delete(:valid_regex) || '[0-9A-Za-z\$\-_\+!\*\',]+' self.request_methods = && .delete(:request_methods) || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains] reset! end |
Instance Attribute Details
#delimiter_chars ⇒ Object (readonly)
Returns the value of attribute delimiter_chars.
10 11 12 |
# File 'lib/usher.rb', line 10 def delimiter_chars @delimiter_chars end |
#delimiters ⇒ Object
Returns the value of attribute delimiters.
10 11 12 |
# File 'lib/usher.rb', line 10 def delimiters @delimiters end |
#delimiters_regex ⇒ Object (readonly)
Returns the value of attribute delimiters_regex.
10 11 12 |
# File 'lib/usher.rb', line 10 def delimiters_regex @delimiters_regex end |
#generator ⇒ Object
Returns the value of attribute generator.
10 11 12 |
# File 'lib/usher.rb', line 10 def generator @generator end |
#grapher ⇒ Object (readonly)
Returns the value of attribute grapher.
10 11 12 |
# File 'lib/usher.rb', line 10 def grapher @grapher end |
#named_routes ⇒ Object (readonly)
Returns the value of attribute named_routes.
10 11 12 |
# File 'lib/usher.rb', line 10 def named_routes @named_routes end |
#parent_route ⇒ Object
Returns the value of attribute parent_route.
10 11 12 |
# File 'lib/usher.rb', line 10 def parent_route @parent_route end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
10 11 12 |
# File 'lib/usher.rb', line 10 def root @root end |
#routes ⇒ Object (readonly)
Returns the value of attribute routes.
10 11 12 |
# File 'lib/usher.rb', line 10 def routes @routes end |
#splitter ⇒ Object (readonly)
Returns the value of attribute splitter.
10 11 12 |
# File 'lib/usher.rb', line 10 def splitter @splitter end |
Instance Method Details
#add_named_route(name, path, options = nil) ⇒ Object
76 77 78 |
# File 'lib/usher.rb', line 76 def add_named_route(name, path, = nil) add_route(path, ).name(name) end |
#add_route(path, options = nil) ⇒ Object
Creates a route from path
and options
path
A path consists a mix of dynamic and static parts delimited by /
Dynamic
Dynamic parts are prefixed with either :, *. :variable matches only one part of the path, whereas *variable can match one or more parts.
Example: /path/:variable/path
would match
-
/path/test/path
-
/path/something_else/path
-
/path/one_more/path
In the above examples, ‘test’, ‘something_else’ and ‘one_more’ respectively would be bound to the key :variable
. However, /path/test/one_more/path
would not be matched.
Example: /path/*variable/path
would match
-
/path/one/two/three/path
-
/path/four/five/path
In the above examples, [‘one’, ‘two’, ‘three’] and [‘four’, ‘five’] respectively would be bound to the key :variable.
As well, variables can have a regex matcher.
Example: /product/{:id,\d+}
would match
-
/product/123
-
/product/4521
But not
-
/product/AE-35
As well, the same logic applies for * variables as well, where only parts matchable by the supplied regex will actually be bound to the variable
Variables can also have a greedy regex matcher. These matchers ignore all delimiters, and continue matching for as long as much as their regex allows.
Example: /product/{!id,hello/world|hello}
would match
-
/product/hello/world
-
/product/hello
Static
Static parts of literal character sequences. For instance, /path/something.html
would match only the same path. As well, static parts can have a regex pattern in them as well, such as /path/something.{html|xml}
which would match only /path/something.html
and /path/something.xml
Optional sections
Sections of a route can be marked as optional by surrounding it with brackets. For instance, in the above static example, /path/something(.html)
would match both /path/something
and /path/something.html
.
One and only one sections
Sections of a route can be marked as “one and only one” by surrounding it with brackets and separating parts of the route with pipes. For instance, the path, /path/something(.xml|.html)
would only match /path/something.xml
and /path/something.html
. Generally its more efficent to use one and only sections over using regex.
options
-
requirements
- After transformation, tests the condition using ===. If it returns false, it raises anUsher::ValidationException
-
conditions
- Accepts any of therequest_methods
specificied in the construction of Usher. This can be either astring
or a regular expression. -
Any other key is interpreted as a requirement for the variable of its name.
169 170 171 172 173 174 175 176 |
# File 'lib/usher.rb', line 169 def add_route(path, = nil) route = get_route(path, ) @root.add(route) @routes << route @grapher.add_route(route) route.parent_route = parent_route if parent_route route end |
#can_generate? ⇒ Boolean
64 65 66 |
# File 'lib/usher.rb', line 64 def can_generate? !@generator.nil? end |
#delete_named_route(name, path, options = nil) ⇒ Object
84 85 86 87 |
# File 'lib/usher.rb', line 84 def delete_named_route(name, path, = nil) delete_route(path, ) @named_routes.delete(name) end |
#delete_route(path, options = nil) ⇒ Object
182 183 184 185 186 187 188 |
# File 'lib/usher.rb', line 182 def delete_route(path, = nil) route = get_route(path, ) @root.delete(route) @routes = @root.unique_routes rebuild_grapher! route end |
#dup ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/usher.rb', line 224 def dup replacement = super original = self inverted_named_routes = original.named_routes.invert replacement.instance_eval do @parser = nil reset! original.routes.each do |route| new_route = route.dup new_route.router = self @root.add(new_route) @routes << new_route if name = inverted_named_routes[route] @named_routes[name] = new_route end end send(:generator=, original.generator.class.new) if original.can_generate? rebuild_grapher! end replacement end |
#empty? ⇒ Boolean
20 21 22 |
# File 'lib/usher.rb', line 20 def empty? @routes.empty? end |
#name(name, route) ⇒ Object
94 95 96 97 |
# File 'lib/usher.rb', line 94 def name(name, route) @named_routes[name] = route route end |
#parser ⇒ Object
60 61 62 |
# File 'lib/usher.rb', line 60 def parser @parser ||= Util::Parser.for_delimiters(self, valid_regex) end |
#path_for_options(options) ⇒ Object
215 216 217 |
# File 'lib/usher.rb', line 215 def () @grapher.find_matching_path() end |
#recognize(request, path = request.path) ⇒ Object
Recognizes a request
and returns nil
or an Usher::Node::Response, which is a struct containing a Usher::Route::Path and an array of arrays containing the extracted parameters.
Request = Struct.new(:path)
set = Usher.new
route = set.add_route('/test')
set.recognize(Request.new('/test')).path.route == route => true
196 197 198 |
# File 'lib/usher.rb', line 196 def recognize(request, path = request.path) @root.find(self, request, path, @splitter.url_split(path)) end |
#recognize_path(path) ⇒ Object
Recognizes a path
and returns nil
or an Usher::Node::Response, which is a struct containing a Usher::Route::Path and an array of arrays containing the extracted parameters. Convenience method for when recognizing on the request object is unneeded.
Request = Struct.new(:path)
set = Usher.new
route = set.add_route('/test')
set.recognize_path('/test').path.route == route => true
206 207 208 |
# File 'lib/usher.rb', line 206 def recognize_path(path) recognize(nil, path) end |
#reset! ⇒ Object Also known as: clear!
35 36 37 38 39 40 |
# File 'lib/usher.rb', line 35 def reset! @root = Node.root(self, request_methods) @named_routes = {} @routes = [] @grapher = Grapher.new end |
#route_count ⇒ Object
24 25 26 |
# File 'lib/usher.rb', line 24 def route_count @routes.size end |