usher 0.5.11 → 0.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +48 -53
- data/VERSION.yml +2 -2
- data/lib/usher.rb +12 -12
- data/lib/usher/delimiters.rb +7 -7
- data/lib/usher/interface.rb +19 -30
- data/lib/usher/interface/{email_interface.rb → email.rb} +1 -1
- data/lib/usher/interface/{merb_interface.rb → merb.rb} +1 -1
- data/lib/usher/interface/{rack_interface.rb → rack.rb} +14 -10
- data/lib/usher/interface/{rack_interface → rack}/mapper.rb +0 -0
- data/lib/usher/interface/rack/route.rb +16 -0
- data/lib/usher/interface/rails20.rb +7 -0
- data/lib/usher/interface/{rails2_2_interface.rb → rails22.rb} +18 -18
- data/lib/usher/interface/{rails2_2_interface → rails22}/mapper.rb +2 -2
- data/lib/usher/interface/{rails2_3_interface.rb → rails23.rb} +1 -1
- data/lib/usher/interface/rails23/mapper.rb +44 -0
- data/lib/usher/interface/{rails3_interface.rb → rails3.rb} +1 -1
- data/lib/usher/interface/{text_interface.rb → text.rb} +1 -1
- data/lib/usher/node.rb +71 -57
- data/lib/usher/route.rb +10 -5
- data/lib/usher/route/static.rb +9 -0
- data/lib/usher/route/variable.rb +28 -9
- data/lib/usher/util.rb +3 -3
- data/lib/usher/util/generate.rb +55 -18
- data/lib/usher/util/parser.rb +25 -18
- data/rails/init.rb +24 -8
- data/spec/private/generate_spec.rb +116 -1
- data/spec/private/generate_with_spec.rb +28 -0
- data/spec/private/rack/dispatch_spec.rb +23 -2
- data/spec/private/rack/route_spec.rb +50 -0
- data/spec/private/rails2_2/generate_spec.rb +1 -1
- data/spec/private/rails2_2/path_spec.rb +1 -1
- data/spec/private/rails2_2/recognize_spec.rb +1 -1
- data/spec/private/rails2_3/generate_spec.rb +1 -1
- data/spec/private/rails2_3/path_spec.rb +1 -1
- data/spec/private/rails2_3/recognize_spec.rb +1 -1
- data/spec/private/recognize_spec.rb +4 -5
- data/spec/private/url_parts_spec.rb +116 -0
- metadata +26 -12
- data/lib/usher/interface/rack_interface/route.rb +0 -16
data/Rakefile
CHANGED
@@ -1,53 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
s.
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.
|
15
|
-
s.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Jeweler
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
Rake::RDocTask.new do |rd|
|
50
|
-
rd.main = "README.rdoc"
|
51
|
-
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
52
|
-
rd.rdoc_dir = 'rdoc'
|
53
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'usher'))
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "usher"
|
9
|
+
s.description = s.summary = "A general purpose routing library"
|
10
|
+
s.email = "joshbuddy@gmail.com"
|
11
|
+
s.homepage = "http://github.com/joshbuddy/usher"
|
12
|
+
s.authors = ["Joshua Hull", 'Jakub Šťastný', 'Daniel Neighman', 'Daniel Vartanov'].sort
|
13
|
+
s.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"]
|
14
|
+
s.add_dependency 'fuzzyhash', '>=0.0.9'
|
15
|
+
s.rubyforge_project = 'joshbuddy-usher'
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec'
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
task :spec => 'spec:all'
|
25
|
+
namespace(:spec) do
|
26
|
+
Spec::Rake::SpecTask.new(:all) do |t|
|
27
|
+
t.spec_opts ||= []
|
28
|
+
t.spec_opts << "-rubygems"
|
29
|
+
t.spec_opts << "--options" << "spec/spec.opts"
|
30
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Run all examples with RCov"
|
36
|
+
Spec::Rake::SpecTask.new('spec_with_rcov') do |t|
|
37
|
+
t.spec_files = FileList['spec/**/*.rb']
|
38
|
+
t.rcov = true
|
39
|
+
t.rcov_opts = ['--exclude', 'spec']
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
desc "Generate documentation"
|
44
|
+
Rake::RDocTask.new do |rd|
|
45
|
+
rd.main = "README.rdoc"
|
46
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
47
|
+
rd.rdoc_dir = 'rdoc'
|
48
|
+
end
|
data/VERSION.yml
CHANGED
data/lib/usher.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
|
2
|
-
require File.join(
|
3
|
-
require File.join(
|
4
|
-
require File.join(
|
5
|
-
require File.join(
|
6
|
-
require File.join(
|
7
|
-
require File.join(
|
8
|
-
require File.join(
|
9
|
-
require File.join(
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
2
|
+
require File.join('usher', 'node')
|
3
|
+
require File.join('usher', 'route')
|
4
|
+
require File.join('usher', 'grapher')
|
5
|
+
require File.join('usher', 'interface')
|
6
|
+
require File.join('usher', 'splitter')
|
7
|
+
require File.join('usher', 'exceptions')
|
8
|
+
require File.join('usher', 'util')
|
9
|
+
require File.join('usher', 'spinoffs', 'strscan_additions')
|
10
|
+
require File.join('usher', 'delimiters')
|
10
11
|
|
11
12
|
class Usher
|
12
13
|
attr_reader :root, :named_routes, :routes, :splitter,
|
@@ -53,8 +54,7 @@ class Usher
|
|
53
54
|
# Array of methods called against the request object for the purposes of matching route requirements.
|
54
55
|
def initialize(options = nil)
|
55
56
|
self.generator = options && options.delete(:generator)
|
56
|
-
|
57
|
-
self.delimiters = Delimiters.new(delimiters_array)
|
57
|
+
self.delimiters = Delimiters.new(options && options.delete(:delimiters) || ['/', '.'])
|
58
58
|
self.valid_regex = options && options.delete(:valid_regex) || '[0-9A-Za-z\$\-_\+!\*\',]+'
|
59
59
|
self.request_methods = options && options.delete(:request_methods)
|
60
60
|
reset!
|
@@ -95,7 +95,7 @@ class Usher
|
|
95
95
|
# route = set.add_route('/test')
|
96
96
|
# set.name(:test, route)
|
97
97
|
def name(name, route)
|
98
|
-
@named_routes[name] = route
|
98
|
+
@named_routes[name.to_sym] = route
|
99
99
|
route
|
100
100
|
end
|
101
101
|
|
data/lib/usher/delimiters.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
class Delimiters < Array
|
2
|
-
|
2
|
+
|
3
|
+
attr_reader :unescaped
|
3
4
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
delimiter
|
5
|
+
def initialize(ary)
|
6
|
+
super ary
|
7
|
+
@unescaped = self.map do |delimiter|
|
8
|
+
(delimiter[0] == ?\\) ? delimiter[1..-1] : delimiter
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def first_in(array)
|
13
13
|
# TODO: should we optimize this O(n*m)? hash or modified or KNP or at leaset sort + b-search. But they are so short
|
14
14
|
|
data/lib/usher/interface.rb
CHANGED
@@ -1,43 +1,32 @@
|
|
1
|
-
# From Extlib
|
2
|
-
module CamelCaseMixin
|
3
|
-
def camel_case
|
4
|
-
return self if self !~ /_/ && self =~ /[A-Z]+.*/
|
5
|
-
split('_').map{|e| e.capitalize}.join
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
# TODO: refactoring: I suggest to use usher/interfaces/rack.rb instead of
|
10
|
-
# usher/interface/rack_interface.rb, it will enable me to simplify this code
|
11
1
|
class Usher
|
12
2
|
module Interface
|
13
|
-
# Get root directory of interfaces of path to specified interface
|
14
|
-
def self.interface_directory
|
15
|
-
File.join(File.dirname(__FILE__), "interface")
|
16
|
-
end
|
17
3
|
|
18
|
-
|
19
|
-
|
20
|
-
|
4
|
+
InterfaceRegistry = {}
|
5
|
+
|
6
|
+
def self.register(name, cls)
|
7
|
+
InterfaceRegistry[name] = cls
|
21
8
|
end
|
22
9
|
|
10
|
+
register(:email, File.join(File.dirname(__FILE__), 'interface', 'email'))
|
11
|
+
register(:merb, File.join(File.dirname(__FILE__), 'interface', 'merb'))
|
12
|
+
register(:rails20, File.join(File.dirname(__FILE__), 'interface', 'rails20'))
|
13
|
+
register(:rails22, File.join(File.dirname(__FILE__), 'interface', 'rails22'))
|
14
|
+
register(:rails23, File.join(File.dirname(__FILE__), 'interface', 'rails23'))
|
15
|
+
register(:rack, File.join(File.dirname(__FILE__), 'interface', 'rack'))
|
16
|
+
register(:rails3, File.join(File.dirname(__FILE__), 'interface', 'rails3'))
|
17
|
+
register(:text, File.join(File.dirname(__FILE__), 'interface', 'text'))
|
18
|
+
|
23
19
|
# Usher::Interface.for(:rack, &block)
|
24
20
|
def self.for(name, &block)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
Usher::Interface.const_get(
|
21
|
+
name = name.to_sym
|
22
|
+
if InterfaceRegistry[name]
|
23
|
+
require InterfaceRegistry[name]
|
24
|
+
const = Usher::Interface.const_get(File.basename(InterfaceRegistry[name]).to_s.split(/_/).map{|e| e.capitalize}.join)
|
25
|
+
const.new(&block)
|
29
26
|
else
|
30
|
-
raise ArgumentError, "Interface #{name} doesn't exist. Choose one of: #{
|
27
|
+
raise ArgumentError, "Interface #{name.inspect} doesn't exist. Choose one of: #{InterfaceRegistry.keys.inspect}"
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
34
|
-
# Array of symbols
|
35
|
-
# Usher::Interface.interfaces
|
36
|
-
# => [:email_interface, :merb_interface, :rack_interface, :rails2_2_interface, :rails2_3_interface, :rails3_interface, :text_interface]
|
37
|
-
def self.interfaces
|
38
|
-
Dir["#{self.interface_directory}/*.rb"].map do |interface|
|
39
|
-
File.basename(interface).sub("_interface.rb", "").to_sym
|
40
|
-
end
|
41
|
-
end
|
42
31
|
end
|
43
32
|
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require "rack"
|
2
|
+
require File.join(File.dirname(__FILE__), 'rack', 'route')
|
2
3
|
|
3
4
|
class Usher
|
4
5
|
module Interface
|
5
|
-
class
|
6
|
-
class Builder < Rack::Builder
|
6
|
+
class Rack
|
7
|
+
class Builder < ::Rack::Builder
|
7
8
|
def initialize(&block)
|
8
|
-
@usher = Usher::Interface::
|
9
|
+
@usher = Usher::Interface::Rack.new
|
9
10
|
super
|
10
11
|
end
|
11
12
|
|
@@ -14,7 +15,10 @@ class Usher
|
|
14
15
|
@ins << @usher unless @ins.last == @usher
|
15
16
|
end
|
16
17
|
|
18
|
+
# it returns route, and because you may want to work with the route,
|
19
|
+
# for example give it a name, we returns the route with GET request
|
17
20
|
def get(path, options = nil, &block)
|
21
|
+
self.map(path, options.merge!(:conditions => {:request_method => "HEAD"}), &block)
|
18
22
|
self.map(path, options.merge!(:conditions => {:request_method => "GET"}), &block)
|
19
23
|
end
|
20
24
|
|
@@ -35,7 +39,7 @@ class Usher
|
|
35
39
|
attr_accessor :app
|
36
40
|
|
37
41
|
def initialize(app = nil, &blk)
|
38
|
-
@app = app || lambda { |env| Rack::Response.new("No route found", 404).finish }
|
42
|
+
@app = app || lambda { |env| ::Rack::Response.new("No route found", 404).finish }
|
39
43
|
@router = Usher.new(:request_methods => [:request_method, :host, :port, :scheme], :generator => Usher::Util::Generators::URL.new)
|
40
44
|
instance_eval(&blk) if blk
|
41
45
|
end
|
@@ -63,11 +67,11 @@ class Usher
|
|
63
67
|
# add("/url", :conditions => {:request_method => "POST"}})
|
64
68
|
# is the same as:
|
65
69
|
# post("/url")
|
66
|
-
|
67
|
-
#
|
68
|
-
#
|
70
|
+
|
71
|
+
# it returns route, and because you may want to work with the route,
|
72
|
+
# for example give it a name, we returns the route with GET request
|
69
73
|
def get(path, options = {})
|
70
|
-
self.add(path, options.merge!(:conditions => {:request_method => "GET"}))
|
74
|
+
self.add(path, options.merge!(:conditions => {:request_method => ["HEAD", "GET"]}))
|
71
75
|
end
|
72
76
|
|
73
77
|
def post(path, options = {})
|
@@ -95,7 +99,7 @@ class Usher
|
|
95
99
|
end
|
96
100
|
|
97
101
|
def call(env)
|
98
|
-
request = Rack::Request.new(env)
|
102
|
+
request = ::Rack::Request.new(env)
|
99
103
|
response = @router.recognize(request, request.path_info)
|
100
104
|
after_match(request, response) if response
|
101
105
|
determine_respondant(response).call(env)
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Usher
|
2
|
+
class Route
|
3
|
+
# add("/index.html").redirect("/")
|
4
|
+
def redirect(path, status = 302)
|
5
|
+
unless (300..399).include?(status)
|
6
|
+
raise ArgumentError, "Status has to be an integer between 300 and 399"
|
7
|
+
end
|
8
|
+
@destination = lambda do |env|
|
9
|
+
response = Rack::Response.new
|
10
|
+
response.redirect(path, status)
|
11
|
+
response.finish
|
12
|
+
end
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require File.join(
|
1
|
+
require File.join('usher', 'interface', 'rails22', 'mapper')
|
2
2
|
|
3
3
|
class Usher
|
4
4
|
module Interface
|
5
|
-
class
|
5
|
+
class Rails22
|
6
6
|
|
7
7
|
attr_reader :usher
|
8
8
|
attr_accessor :configuration_file
|
@@ -10,9 +10,12 @@ class Usher
|
|
10
10
|
def initialize
|
11
11
|
reset!
|
12
12
|
end
|
13
|
-
|
14
|
-
def reset!
|
15
|
-
|
13
|
+
|
14
|
+
def reset!(options={})
|
15
|
+
options[:generator] = options[:generator] || Usher::Util::Generators::URL.new
|
16
|
+
options[:request_methods] = options[:request_methods] || [:protocol, :domain, :port, :query_string, :remote_ip, :user_agent, :referer, :method, :subdomains]
|
17
|
+
|
18
|
+
@usher = Usher.new(options)
|
16
19
|
@module ||= Module.new
|
17
20
|
@module.instance_methods.each do |selector|
|
18
21
|
@module.class_eval { remove_method selector }
|
@@ -32,7 +35,7 @@ class Usher
|
|
32
35
|
add_route('/:controller', options.merge({:action => 'index'}))
|
33
36
|
@controller_route_added = true
|
34
37
|
end
|
35
|
-
|
38
|
+
|
36
39
|
options[:action] = 'index' unless options[:action]
|
37
40
|
|
38
41
|
path[0, 0] = '/' unless path[0] == ?/
|
@@ -109,25 +112,22 @@ class Usher
|
|
109
112
|
reload
|
110
113
|
end
|
111
114
|
|
112
|
-
def draw
|
113
|
-
reset!
|
115
|
+
def draw(options={})
|
116
|
+
reset!(options)
|
114
117
|
yield Mapper.new(self)
|
115
118
|
install_helpers
|
116
119
|
end
|
117
120
|
|
118
121
|
def install_helpers(destinations = [ActionController::Base, ActionView::Base], regenerate_code = false)
|
119
|
-
|
120
|
-
|
121
|
-
@usher.
|
122
|
-
@module.module_eval <<-end_eval # We use module_eval to avoid leaks
|
123
|
-
def #{name}_url(options = {})
|
124
|
-
ActionController::Routing::UsherRoutes.generate(options, {}, :generate, :#{name})
|
125
|
-
end
|
126
|
-
end_eval
|
127
|
-
end
|
128
|
-
d.__send__(:include, @module)
|
122
|
+
Array(destinations).each do |destination|
|
123
|
+
destination.module_eval { include Helpers }
|
124
|
+
destination.__send__(:include, @usher.generator.generation_module)
|
129
125
|
end
|
130
126
|
end
|
127
|
+
|
128
|
+
def routes
|
129
|
+
@usher.routes
|
130
|
+
end
|
131
131
|
|
132
132
|
end
|
133
133
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class Usher
|
2
2
|
module Interface
|
3
|
-
class
|
3
|
+
class Rails22
|
4
4
|
|
5
5
|
class Mapper #:doc:
|
6
6
|
def initialize(set) #:nodoc:
|
7
7
|
@set = set
|
8
8
|
end
|
9
9
|
|
10
|
-
def connect(path, options =
|
10
|
+
def connect(path, options = {})
|
11
11
|
@set.add_route(path, options)
|
12
12
|
end
|
13
13
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Usher
|
2
|
+
module Interface
|
3
|
+
class Rails23
|
4
|
+
|
5
|
+
class Mapper #:doc:
|
6
|
+
def initialize(set) #:nodoc:
|
7
|
+
@set = set
|
8
|
+
end
|
9
|
+
|
10
|
+
def connect(path, options = {})
|
11
|
+
@set.add_route(path, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def root(options = {})
|
15
|
+
if options.is_a?(Symbol)
|
16
|
+
if source_route = @set.named_routes[options]
|
17
|
+
options = source_route.conditions.blank? ?
|
18
|
+
source_route.options.merge({ :conditions => source_route.conditions }) : source_route.options
|
19
|
+
end
|
20
|
+
end
|
21
|
+
named_route(:root, '/', options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def named_route(name, path, options = nil)
|
25
|
+
@set.add_named_route(name, path, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def namespace(name, options = {}, &block)
|
29
|
+
if options[:namespace]
|
30
|
+
with_options({:path_prefix => "#{options.delete(:path_prefix)}/#{name}", :name_prefix => "#{options.delete(:name_prefix)}#{name}_", :namespace => "#{options.delete(:namespace)}#{name}/" }.merge(options), &block)
|
31
|
+
else
|
32
|
+
with_options({:path_prefix => name, :name_prefix => "#{name}_", :namespace => "#{name}/" }.merge(options), &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(route_name, *args, &proc) #:nodoc:
|
37
|
+
super unless args.length >= 1 && proc.nil?
|
38
|
+
@set.add_named_route(route_name, *args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|