sinatra-named-routes-subdomains 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +15 -0
- data/README.md +14 -0
- data/lib/sinatra/named_routes.rb +72 -0
- data/lib/sinatra/route_parser.rb +175 -0
- data/lib/sinatra/version.rb +5 -0
- data/sinatra-named-routes-0.1.0.gem +0 -0
- data/sinatra-named-routes-subdomains.gemspec +22 -0
- metadata +72 -0
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in sinatra-named-routes.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem 'rake'
|
8
|
+
gem 'sinatra-contrib'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'guard-rspec'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem 'simplecov', :require => false
|
15
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Sinatra Named Routes w/ Subdomain support
|
2
|
+
|
3
|
+
Based on sinatra-named-routes by ckhampus: https://github.com/ckhampus/sinatra-named-routes.
|
4
|
+
|
5
|
+
## Subdomain Usage
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
map :named_route, '/myroute/:some_id'
|
9
|
+
url( :named_route, true, :some_id => 123, :subdomain => 'mysubdomain' )
|
10
|
+
```
|
11
|
+
|
12
|
+
```
|
13
|
+
http://mysubdomain.myhost.com/myroute/123
|
14
|
+
```
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'version')
|
2
|
+
require File.join(File.dirname(__FILE__), 'route_parser')
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
module NamedRoutes
|
6
|
+
module Helpers
|
7
|
+
|
8
|
+
# Generates the absolute URI for a given path in the app.
|
9
|
+
# Takes Rack routers and reverse proxies into account.
|
10
|
+
# Extended support passing in named route and parameters.
|
11
|
+
def uri( addr = nil, absolute = true, params = nil )
|
12
|
+
if addr.is_a? Symbol
|
13
|
+
addr = NamedRoutes.get_path( addr, params )
|
14
|
+
end
|
15
|
+
|
16
|
+
return addr if addr =~ /\A[A-z][A-z0-9\+\.\-]*:/
|
17
|
+
|
18
|
+
uri = [host = ""]
|
19
|
+
if absolute
|
20
|
+
host << "http#{'s' if request.secure?}://"
|
21
|
+
if request.forwarded? or request.port != (request.secure? ? 443 : 80)
|
22
|
+
domain = request.host_with_port
|
23
|
+
else
|
24
|
+
domain = request.host
|
25
|
+
end
|
26
|
+
|
27
|
+
if !params.nil? && !params[:subdomain].nil?
|
28
|
+
host << domain.gsub(/^([a-zA-Z-]+)\./, "#{params[:subdomain]}.")
|
29
|
+
else
|
30
|
+
host << domain
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
uri << (addr ? addr : request.path_info).to_s
|
35
|
+
File.join uri
|
36
|
+
end
|
37
|
+
|
38
|
+
alias :to :uri
|
39
|
+
alias :url :uri
|
40
|
+
end
|
41
|
+
|
42
|
+
# Maps a path to name.
|
43
|
+
def map(name, path)
|
44
|
+
NamedRoutes.routes[name] = Route.new path
|
45
|
+
end
|
46
|
+
|
47
|
+
alias :bind :map
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def route(verb, path, options={}, &block)
|
52
|
+
if path.is_a?(Symbol)
|
53
|
+
path = NamedRoutes.routes[path].source
|
54
|
+
end
|
55
|
+
|
56
|
+
super(verb, path, options, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.get_path(name, params = {})
|
60
|
+
raise ArgumentError, "No route with the name #{name} exists." if NamedRoutes.routes.nil?
|
61
|
+
NamedRoutes.routes[name].build params
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.routes
|
65
|
+
@@routes ||= {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.registered(app)
|
69
|
+
app.helpers NamedRoutes::Helpers
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module BlueRoutes
|
3
|
+
class Route
|
4
|
+
attr_reader :source
|
5
|
+
|
6
|
+
def initialize(route)
|
7
|
+
route = route.source if route.is_a? Regexp
|
8
|
+
|
9
|
+
@source = route
|
10
|
+
@input = StringScanner.new(route)
|
11
|
+
@output = []
|
12
|
+
|
13
|
+
parse
|
14
|
+
end
|
15
|
+
|
16
|
+
def build(params = {})
|
17
|
+
path = []
|
18
|
+
params = {} if params.nil?
|
19
|
+
|
20
|
+
@output.each_index do |index|
|
21
|
+
item = @output[index]
|
22
|
+
next_item = @output.fetch(index + 1, nil)
|
23
|
+
|
24
|
+
case item[:token]
|
25
|
+
when :slash
|
26
|
+
@trailing_slash = item[:optional]
|
27
|
+
path << '/'
|
28
|
+
when :dot
|
29
|
+
@trailing_dot = item[:optional]
|
30
|
+
path << '.'
|
31
|
+
when :plus
|
32
|
+
path << '+'
|
33
|
+
when :splat
|
34
|
+
if params.is_a? Hash
|
35
|
+
raise ArgumentError, 'No parameters passed.' if params[:splat].empty?
|
36
|
+
path << params[:splat].shift
|
37
|
+
else
|
38
|
+
raise ArgumentError, 'No enough parameters passed.' if params.empty?
|
39
|
+
path << params.shift
|
40
|
+
end
|
41
|
+
when :path
|
42
|
+
path << item[:value]
|
43
|
+
when :named_param
|
44
|
+
item_key = item[:value]
|
45
|
+
|
46
|
+
if params.has_key? item_key
|
47
|
+
path << params.delete(item_key)
|
48
|
+
else
|
49
|
+
raise ArgumentError, "No value passed for '#{item_key.to_s}'" unless item[:optional]
|
50
|
+
end
|
51
|
+
when :regexp
|
52
|
+
name = /#{item[:value]}/.names
|
53
|
+
|
54
|
+
if name.any?
|
55
|
+
name = name.first.to_sym
|
56
|
+
|
57
|
+
if params.has_key? name
|
58
|
+
path << params.delete(name)
|
59
|
+
else
|
60
|
+
raise ArgumentError, "No value passed for '#{name.to_s}'" unless item[:optional]
|
61
|
+
end
|
62
|
+
else
|
63
|
+
if params.is_a? Hash
|
64
|
+
raise ArgumentError, 'No enough parameters passed.' if params[:captures].empty? and !item[:optional]
|
65
|
+
path << params[:captures].shift
|
66
|
+
else
|
67
|
+
raise ArgumentError, 'No enough parameters passed.' if params.empty?
|
68
|
+
path << params.shift
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
path = path.join
|
75
|
+
|
76
|
+
if @trailing_dot
|
77
|
+
path = path.chomp '.'
|
78
|
+
end
|
79
|
+
|
80
|
+
if @trailing_slash
|
81
|
+
path = path.chomp '/'
|
82
|
+
end
|
83
|
+
|
84
|
+
path
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def is_optional?
|
90
|
+
@output.last[:optional] = @input.scan(/\?/) ? true : false
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse
|
94
|
+
while token = parse_slash || parse_path || parse_named_param ||
|
95
|
+
parse_dot || parse_plus || parse_splat || parse_regexp
|
96
|
+
@output << token
|
97
|
+
is_optional?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_slash
|
102
|
+
if @input.scan(/\//)
|
103
|
+
{
|
104
|
+
:token => :slash
|
105
|
+
}
|
106
|
+
else
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def parse_dot
|
112
|
+
if @input.scan(/\./)
|
113
|
+
{
|
114
|
+
:token => :dot
|
115
|
+
}
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse_plus
|
122
|
+
if @input.scan(/\+/)
|
123
|
+
{
|
124
|
+
:token => :plus
|
125
|
+
}
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_splat
|
132
|
+
if @input.scan(/\*/)
|
133
|
+
{
|
134
|
+
:token => :splat
|
135
|
+
}
|
136
|
+
else
|
137
|
+
nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def parse_path
|
142
|
+
if @input.scan(/\w+/)
|
143
|
+
{
|
144
|
+
:token => :path,
|
145
|
+
:value => @input.matched
|
146
|
+
}
|
147
|
+
else
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def parse_named_param
|
153
|
+
if @input.scan(/:[^\W]*/)
|
154
|
+
{
|
155
|
+
:token => :named_param,
|
156
|
+
:value => @input.matched.sub(':', '').to_sym
|
157
|
+
}
|
158
|
+
else
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def parse_regexp
|
164
|
+
if @input.scan(/\([^\)]*\)/)
|
165
|
+
{
|
166
|
+
:token => :regexp,
|
167
|
+
:value => @input.matched
|
168
|
+
}
|
169
|
+
else
|
170
|
+
nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'sinatra/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'sinatra-named-routes-subdomains'
|
7
|
+
s.version = Sinatra::BlueRoutes::VERSION
|
8
|
+
s.authors = ['Adam Zerlin']
|
9
|
+
s.email = ['adam@adamzerlin.com']
|
10
|
+
s.homepage = 'https://github.com/adamzerlin/sinatra-named-routes'
|
11
|
+
s.summary = %q{Named Routes for Sinatra with Subdomains}
|
12
|
+
s.description = %q{Allows the use of named routes and custom subdomains in Sinatra applications. Based heavily on ckhampus' sinatra-named-routes.}
|
13
|
+
|
14
|
+
s.rubyforge_project = 'sinatra-named-routes-subdomains'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
|
21
|
+
s.add_dependency 'sinatra'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-named-routes-subdomains
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Zerlin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sinatra
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: !binary |-
|
21
|
+
MA==
|
22
|
+
none: false
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: !binary |-
|
28
|
+
MA==
|
29
|
+
none: false
|
30
|
+
prerelease: false
|
31
|
+
type: :runtime
|
32
|
+
description: Allows the use of named routes and custom subdomains in Sinatra applications. Based heavily on ckhampus' sinatra-named-routes.
|
33
|
+
email:
|
34
|
+
- adam@adamzerlin.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- Gemfile
|
40
|
+
- README.md
|
41
|
+
- lib/sinatra/named_routes.rb
|
42
|
+
- lib/sinatra/route_parser.rb
|
43
|
+
- lib/sinatra/version.rb
|
44
|
+
- sinatra-named-routes-0.1.0.gem
|
45
|
+
- sinatra-named-routes-subdomains.gemspec
|
46
|
+
homepage: https://github.com/adamzerlin/sinatra-named-routes
|
47
|
+
licenses: []
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: !binary |-
|
57
|
+
MA==
|
58
|
+
none: false
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: !binary |-
|
64
|
+
MA==
|
65
|
+
none: false
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project: sinatra-named-routes-subdomains
|
68
|
+
rubygems_version: 1.8.24
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Named Routes for Sinatra with Subdomains
|
72
|
+
test_files: []
|