js-routes 0.7.5 → 0.8.0
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/Gemfile +1 -1
- data/Gemfile.lock +45 -47
- data/Readme.md +31 -22
- data/VERSION +1 -1
- data/js-routes.gemspec +5 -5
- data/lib/js_routes.rb +47 -60
- data/lib/js_routes/engine.rb +1 -1
- data/lib/routes.js +83 -51
- data/spec/js_routes_spec.rb +6 -0
- data/spec/post_rails_init_spec.rb +47 -63
- data/spec/spec_helper.rb +4 -4
- metadata +16 -16
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,37 +1,34 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
actionmailer (3.1
|
5
|
-
actionpack (= 3.1
|
6
|
-
mail (~> 2.
|
7
|
-
actionpack (3.1
|
8
|
-
activemodel (= 3.1
|
9
|
-
activesupport (= 3.1
|
4
|
+
actionmailer (3.2.1)
|
5
|
+
actionpack (= 3.2.1)
|
6
|
+
mail (~> 2.4.0)
|
7
|
+
actionpack (3.2.1)
|
8
|
+
activemodel (= 3.2.1)
|
9
|
+
activesupport (= 3.2.1)
|
10
10
|
builder (~> 3.0.0)
|
11
11
|
erubis (~> 2.7.0)
|
12
|
-
|
13
|
-
rack (~> 1.
|
14
|
-
rack-cache (~> 1.
|
15
|
-
rack-mount (~> 0.8.2)
|
12
|
+
journey (~> 1.0.1)
|
13
|
+
rack (~> 1.4.0)
|
14
|
+
rack-cache (~> 1.1)
|
16
15
|
rack-test (~> 0.6.1)
|
17
|
-
sprockets (~> 2.
|
18
|
-
activemodel (3.1
|
19
|
-
activesupport (= 3.1
|
20
|
-
bcrypt-ruby (~> 3.0.0)
|
16
|
+
sprockets (~> 2.1.2)
|
17
|
+
activemodel (3.2.1)
|
18
|
+
activesupport (= 3.2.1)
|
21
19
|
builder (~> 3.0.0)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
arel (~> 2.2.1)
|
20
|
+
activerecord (3.2.1)
|
21
|
+
activemodel (= 3.2.1)
|
22
|
+
activesupport (= 3.2.1)
|
23
|
+
arel (~> 3.0.0)
|
27
24
|
tzinfo (~> 0.3.29)
|
28
|
-
activeresource (3.1
|
29
|
-
activemodel (= 3.1
|
30
|
-
activesupport (= 3.1
|
31
|
-
activesupport (3.1
|
25
|
+
activeresource (3.2.1)
|
26
|
+
activemodel (= 3.2.1)
|
27
|
+
activesupport (= 3.2.1)
|
28
|
+
activesupport (3.2.1)
|
29
|
+
i18n (~> 0.6)
|
32
30
|
multi_json (~> 1.0)
|
33
|
-
arel (
|
34
|
-
bcrypt-ruby (3.0.1)
|
31
|
+
arel (3.0.0)
|
35
32
|
builder (3.0.0)
|
36
33
|
diff-lcs (1.1.3)
|
37
34
|
erubis (2.7.0)
|
@@ -42,41 +39,42 @@ GEM
|
|
42
39
|
bundler (~> 1.0)
|
43
40
|
git (>= 1.2.5)
|
44
41
|
rake
|
42
|
+
journey (1.0.1)
|
43
|
+
json (1.6.5)
|
45
44
|
libv8 (3.3.10.4)
|
46
|
-
mail (2.
|
45
|
+
mail (2.4.1)
|
47
46
|
i18n (>= 0.4.0)
|
48
47
|
mime-types (~> 1.16)
|
49
48
|
treetop (~> 1.4.8)
|
50
|
-
mime-types (1.
|
51
|
-
multi_json (1.0.
|
52
|
-
polyglot (0.3.
|
53
|
-
rack (1.
|
54
|
-
rack-cache (1.
|
49
|
+
mime-types (1.17.2)
|
50
|
+
multi_json (1.0.4)
|
51
|
+
polyglot (0.3.3)
|
52
|
+
rack (1.4.1)
|
53
|
+
rack-cache (1.1)
|
55
54
|
rack (>= 0.4)
|
56
|
-
rack-mount (0.8.3)
|
57
|
-
rack (>= 1.0.0)
|
58
55
|
rack-ssl (1.3.2)
|
59
56
|
rack
|
60
57
|
rack-test (0.6.1)
|
61
58
|
rack (>= 1.0)
|
62
|
-
rails (3.1
|
63
|
-
actionmailer (= 3.1
|
64
|
-
actionpack (= 3.1
|
65
|
-
activerecord (= 3.1
|
66
|
-
activeresource (= 3.1
|
67
|
-
activesupport (= 3.1
|
59
|
+
rails (3.2.1)
|
60
|
+
actionmailer (= 3.2.1)
|
61
|
+
actionpack (= 3.2.1)
|
62
|
+
activerecord (= 3.2.1)
|
63
|
+
activeresource (= 3.2.1)
|
64
|
+
activesupport (= 3.2.1)
|
68
65
|
bundler (~> 1.0)
|
69
|
-
railties (= 3.1
|
70
|
-
railties (3.1
|
71
|
-
actionpack (= 3.1
|
72
|
-
activesupport (= 3.1
|
66
|
+
railties (= 3.2.1)
|
67
|
+
railties (3.2.1)
|
68
|
+
actionpack (= 3.2.1)
|
69
|
+
activesupport (= 3.2.1)
|
73
70
|
rack-ssl (~> 1.3.2)
|
74
71
|
rake (>= 0.8.7)
|
75
72
|
rdoc (~> 3.4)
|
76
73
|
thor (~> 0.14.6)
|
77
74
|
rake (0.9.2)
|
78
75
|
rcov (0.9.9)
|
79
|
-
rdoc (3.
|
76
|
+
rdoc (3.12)
|
77
|
+
json (~> 1.4)
|
80
78
|
rspec (2.7.0)
|
81
79
|
rspec-core (~> 2.7.0)
|
82
80
|
rspec-expectations (~> 2.7.0)
|
@@ -85,7 +83,7 @@ GEM
|
|
85
83
|
rspec-expectations (2.7.0)
|
86
84
|
diff-lcs (~> 1.1.2)
|
87
85
|
rspec-mocks (2.7.0)
|
88
|
-
sprockets (2.
|
86
|
+
sprockets (2.1.2)
|
89
87
|
hike (~> 1.2)
|
90
88
|
rack (~> 1.0)
|
91
89
|
tilt (~> 1.1, != 1.3.0)
|
@@ -96,7 +94,7 @@ GEM
|
|
96
94
|
treetop (1.4.10)
|
97
95
|
polyglot
|
98
96
|
polyglot (>= 0.3.1)
|
99
|
-
tzinfo (0.3.
|
97
|
+
tzinfo (0.3.31)
|
100
98
|
|
101
99
|
PLATFORMS
|
102
100
|
ruby
|
@@ -104,7 +102,7 @@ PLATFORMS
|
|
104
102
|
DEPENDENCIES
|
105
103
|
bundler (~> 1.0.0)
|
106
104
|
jeweler (~> 1.6.2)
|
107
|
-
rails (>= 3.
|
105
|
+
rails (>= 3.2)
|
108
106
|
rcov
|
109
107
|
rspec (~> 2.7.0)
|
110
108
|
therubyracer
|
data/Readme.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# JsRoutes
|
2
2
|
|
3
3
|
Generates javascript file that defines all Rails named routes as javascript helpers
|
4
4
|
|
5
|
-
|
5
|
+
## Intallation
|
6
6
|
|
7
7
|
Your Rails Gemfile:
|
8
8
|
|
@@ -10,44 +10,53 @@ Your Rails Gemfile:
|
|
10
10
|
gem "js-routes"
|
11
11
|
```
|
12
12
|
|
13
|
-
|
13
|
+
### Basic Setup (Asset Pipeline)
|
14
|
+
|
15
|
+
Require js routes file in `application.js` or other bundle
|
16
|
+
|
17
|
+
``` js
|
18
|
+
/*
|
19
|
+
= require js-routes
|
20
|
+
*/
|
21
|
+
```
|
22
|
+
|
23
|
+
**Optional**: If you need to customize routes file create initializer, like `config/initializers/jsroutes.rb`:
|
14
24
|
|
15
25
|
``` ruby
|
16
|
-
JsRoutes.
|
17
|
-
|
26
|
+
JsRoutes.setup do |config|
|
27
|
+
config.option = value
|
18
28
|
})
|
19
29
|
```
|
20
30
|
|
21
31
|
Available options:
|
22
32
|
|
23
|
-
*
|
24
|
-
|
25
|
-
* `#{Rails.root}/public/javascripts/routes.js` for Rails < 3.1
|
26
|
-
* `:default_format` - Format to append to urls. Default: blank
|
27
|
-
* `:exclude` - Array of regexps to exclude from js routes. Default: []
|
33
|
+
* `default_format` - Format to append to urls. Default: blank
|
34
|
+
* `exclude` - Array of regexps to exclude from js routes. Default: []
|
28
35
|
* Note that regexp applied to **named route** not to *URL*
|
29
|
-
*
|
36
|
+
* `include` - Array of regexps to include in js routes. Default: []
|
30
37
|
* Note that regexp applied to **named route** not to *URL*
|
31
|
-
*
|
38
|
+
* `namespace` - global object used to access routes. Default: `Routes`
|
32
39
|
* Supports nested namespace like `MyProject.routes`
|
33
|
-
*
|
34
|
-
|
40
|
+
* `prefix` - String representing a url path to prepend to all paths. Default: blank
|
41
|
+
|
42
|
+
|
43
|
+
### Advanced Setup
|
35
44
|
|
36
|
-
|
45
|
+
You can generate routes files on the application side like this:
|
37
46
|
|
38
47
|
``` ruby
|
39
|
-
JsRoutes.generate!(
|
40
|
-
JsRoutes.generate!(
|
48
|
+
JsRoutes.generate!("#{path}/app_routes.js", :namespace => "AppRoutes", :exclude => /^admin_/, :default_format => "json")
|
49
|
+
JsRoutes.generate!("#{path}/adm_routes.js", :namespace => "AdmRoutes", :include => /^admin_/, :default_format => "json")
|
41
50
|
```
|
42
51
|
|
43
|
-
In order to generate
|
52
|
+
In order to generate javascript to string and manipulate them yourself use:
|
44
53
|
Like:
|
45
54
|
|
46
55
|
``` ruby
|
47
56
|
routes_js = JsRoutes.generate(options)
|
48
57
|
```
|
49
58
|
|
50
|
-
|
59
|
+
## Usage
|
51
60
|
|
52
61
|
Configuration above will create a nice javascript file with `Routes` object that has all the rails routes available:
|
53
62
|
|
@@ -75,13 +84,13 @@ In order to make routes helpers available globally:
|
|
75
84
|
jQuery.extend(window, Routes)
|
76
85
|
```
|
77
86
|
|
78
|
-
|
87
|
+
## What about security?
|
79
88
|
|
80
89
|
js-routes itself do not have security holes. It makes URLs
|
81
90
|
without access protection more reachable by potential attacker.
|
82
91
|
In order to prevent this use `:exclude` option for sensitive urls like `/admin_/`
|
83
92
|
|
84
|
-
|
93
|
+
## Spork
|
85
94
|
|
86
95
|
When using Spork and `Spork.trap_method(Rails::Application::RoutesReloader, :reload!)` you should also do:
|
87
96
|
|
@@ -89,7 +98,7 @@ When using Spork and `Spork.trap_method(Rails::Application::RoutesReloader, :rel
|
|
89
98
|
Spork.trap_method(JsRoutes, :generate!)
|
90
99
|
```
|
91
100
|
|
92
|
-
|
101
|
+
## Advantages over alternatives
|
93
102
|
|
94
103
|
There are some alternatives available. Most of them has only basic feature and don't reach the level of quality I accept.
|
95
104
|
Advantages of this one are:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0
|
data/js-routes.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "js-routes"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.8.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Bogdan Gusiev"]
|
12
|
-
s.date = "2012-02
|
12
|
+
s.date = "2012-03-02"
|
13
13
|
s.description = "Generates javascript file that defines all Rails named routes as javascript helpers"
|
14
14
|
s.email = "agresso@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -46,14 +46,14 @@ Gem::Specification.new do |s|
|
|
46
46
|
s.specification_version = 3
|
47
47
|
|
48
48
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
-
s.add_runtime_dependency(%q<rails>, [">= 3.
|
49
|
+
s.add_runtime_dependency(%q<rails>, [">= 3.2"])
|
50
50
|
s.add_development_dependency(%q<therubyracer>, [">= 0"])
|
51
51
|
s.add_development_dependency(%q<rspec>, ["~> 2.7.0"])
|
52
52
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
53
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
54
54
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
55
55
|
else
|
56
|
-
s.add_dependency(%q<rails>, [">= 3.
|
56
|
+
s.add_dependency(%q<rails>, [">= 3.2"])
|
57
57
|
s.add_dependency(%q<therubyracer>, [">= 0"])
|
58
58
|
s.add_dependency(%q<rspec>, ["~> 2.7.0"])
|
59
59
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -61,7 +61,7 @@ Gem::Specification.new do |s|
|
|
61
61
|
s.add_dependency(%q<rcov>, [">= 0"])
|
62
62
|
end
|
63
63
|
else
|
64
|
-
s.add_dependency(%q<rails>, [">= 3.
|
64
|
+
s.add_dependency(%q<rails>, [">= 3.2"])
|
65
65
|
s.add_dependency(%q<therubyracer>, [">= 0"])
|
66
66
|
s.add_dependency(%q<rspec>, ["~> 2.7.0"])
|
67
67
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
data/lib/js_routes.rb
CHANGED
@@ -4,11 +4,7 @@ class JsRoutes
|
|
4
4
|
# OPTIONS
|
5
5
|
#
|
6
6
|
|
7
|
-
DEFAULT_PATH =
|
8
|
-
File.join('app','assets','javascripts','routes.js')
|
9
|
-
else
|
10
|
-
File.join('public','javascripts','routes.js')
|
11
|
-
end
|
7
|
+
DEFAULT_PATH = File.join('app','assets','javascripts','routes.js')
|
12
8
|
|
13
9
|
DEFAULTS = {
|
14
10
|
:namespace => "Routes",
|
@@ -19,6 +15,18 @@ class JsRoutes
|
|
19
15
|
:prefix => ""
|
20
16
|
}
|
21
17
|
|
18
|
+
# We encode node symbols as integer to reduce the routes.js file size
|
19
|
+
NODE_TYPES = {
|
20
|
+
:GROUP => 1,
|
21
|
+
:CAT => 2,
|
22
|
+
:SYMBOL => 3,
|
23
|
+
:OR => 4,
|
24
|
+
:STAR => 5,
|
25
|
+
:LITERAL => 6,
|
26
|
+
:SLASH => 7,
|
27
|
+
:DOT => 8
|
28
|
+
}
|
29
|
+
|
22
30
|
class Options < Struct.new(*DEFAULTS.keys)
|
23
31
|
def to_hash
|
24
32
|
Hash[*members.zip(values).flatten(1)].symbolize_keys
|
@@ -44,19 +52,27 @@ class JsRoutes
|
|
44
52
|
new(opts).generate
|
45
53
|
end
|
46
54
|
|
47
|
-
def generate!(opts = {})
|
48
|
-
|
55
|
+
def generate!(file_name, opts = {})
|
56
|
+
if file_name.is_a?(Hash)
|
57
|
+
opts = file_name
|
58
|
+
file_name = opts[:file]
|
59
|
+
end
|
60
|
+
new(opts).generate!(file_name)
|
49
61
|
end
|
50
62
|
|
51
63
|
# Under rails 3.1.1 and higher, perform a check to ensure that the
|
52
64
|
# full environment will be available during asset compilation.
|
53
65
|
# This is required to ensure routes are loaded.
|
54
66
|
def assert_usable_configuration!
|
55
|
-
|
67
|
+
unless Rails.application.config.assets.initialize_on_precompile
|
56
68
|
raise("Cannot precompile js-routes unless environment is initialized. Please set config.assets.initialize_on_precompile to true.")
|
57
69
|
end
|
58
70
|
true
|
59
71
|
end
|
72
|
+
|
73
|
+
def json(string)
|
74
|
+
ActiveSupport::JSON.encode(string)
|
75
|
+
end
|
60
76
|
end
|
61
77
|
|
62
78
|
#
|
@@ -72,15 +88,16 @@ class JsRoutes
|
|
72
88
|
js.gsub!("NAMESPACE", @options[:namespace])
|
73
89
|
js.gsub!("DEFAULT_FORMAT", @options[:default_format].to_s)
|
74
90
|
js.gsub!("PREFIX", @options[:prefix])
|
91
|
+
js.gsub!("NODE_TYPES", json(NODE_TYPES))
|
75
92
|
js.gsub!("ROUTES", js_routes)
|
76
93
|
end
|
77
94
|
|
78
|
-
def generate!
|
95
|
+
def generate!(file_name)
|
79
96
|
# Some libraries like Devise do not yet loaded their routes so we will wait
|
80
97
|
# until initialization process finish
|
81
98
|
# https://github.com/railsware/js-routes/issues/7
|
82
99
|
Rails.configuration.after_initialize do
|
83
|
-
File.open(Rails.root.join(
|
100
|
+
File.open(Rails.root.join(file_name || DEFAULT_PATH), 'w') do |f|
|
84
101
|
f.write generate
|
85
102
|
end
|
86
103
|
end
|
@@ -107,68 +124,38 @@ class JsRoutes
|
|
107
124
|
end
|
108
125
|
|
109
126
|
def build_js(route)
|
110
|
-
params = build_params route
|
111
127
|
_ = <<-JS.strip!
|
112
|
-
// #{route.name} => #{
|
113
|
-
#{route.name}_path: function(#{(
|
114
|
-
return Utils.build_path(#{
|
128
|
+
// #{route.name} => #{route.path.spec}
|
129
|
+
#{route.name}_path: function(#{build_params(route)}) {
|
130
|
+
return Utils.build_path(#{json(route.required_parts)}, #{json(serialize(route.path.spec))}, arguments)
|
115
131
|
}
|
116
132
|
JS
|
117
133
|
end
|
118
134
|
|
119
|
-
|
120
|
-
|
121
|
-
def optional_params(route)
|
122
|
-
if Rails.version >= "3.2.0"
|
123
|
-
return route.optional_parts.map(&:to_s)
|
124
|
-
end
|
125
|
-
path_info = route.conditions[:path_info]
|
126
|
-
path_info_source = path_info.source
|
127
|
-
if RUBY_VERSION >= '1.9.2'
|
128
|
-
optional_named_captures_regexp = /\?\:.+?\(\?\<(.+?)\>/
|
129
|
-
path_info_source.scan(optional_named_captures_regexp).flatten
|
130
|
-
else
|
131
|
-
re = Regexp.escape("([^/.?]+)")
|
132
|
-
optional_named_captures_regexp = /#{re}|\(\?\:.+?\)\?/
|
133
|
-
captures = path_info_source.scan(optional_named_captures_regexp).flatten
|
134
|
-
named_captures = path_info.named_captures.to_a.sort_by {|cap|cap.last.first}
|
135
|
-
captures.zip(named_captures).map do |type, (name, pos)|
|
136
|
-
name unless type == '([^/.?]+)'
|
137
|
-
end.compact
|
138
|
-
end
|
135
|
+
def json(string)
|
136
|
+
self.class.json(string)
|
139
137
|
end
|
140
138
|
|
141
139
|
def build_params route
|
142
|
-
|
140
|
+
params = route.required_parts.map do |name|
|
143
141
|
# prepending each parameter name with underscore
|
144
142
|
# to prevent conflict with JS reserved words
|
145
143
|
"_" + name.to_s
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
def path_parts route
|
151
|
-
route_spec(route).gsub(/\(\.:format\)$/, "").split(/:[a-z\-_]+/)
|
144
|
+
end << "options"
|
145
|
+
params.join(", ")
|
152
146
|
end
|
153
147
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
optional_named_captures = optional_params(route)
|
167
|
-
route.conditions[:path_info].named_captures.to_a.sort_by do |cap1|
|
168
|
-
# Hash is not ordered in Ruby 1.8.7
|
169
|
-
cap1.last.first
|
170
|
-
end.map(&:first).reject do |name|
|
171
|
-
optional_named_captures.include?(name.to_s)
|
172
|
-
end
|
148
|
+
# This function serializes Journey route into JSON structure
|
149
|
+
# We do not use Hash for human readable serialization
|
150
|
+
# And preffer Array serialization because it is shorter.
|
151
|
+
# Routes.js file will be smaller.
|
152
|
+
def serialize(spec)
|
153
|
+
return nil unless spec
|
154
|
+
return spec.tr(':', '') if spec.is_a?(String)
|
155
|
+
[
|
156
|
+
NODE_TYPES[spec.type],
|
157
|
+
serialize(spec.left),
|
158
|
+
spec.respond_to?(:right) && serialize(spec.right)
|
159
|
+
]
|
173
160
|
end
|
174
161
|
end
|
data/lib/js_routes/engine.rb
CHANGED
data/lib/routes.js
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
(function(){
|
2
2
|
|
3
|
+
function ParameterMissing(message) {
|
4
|
+
this.message = message;
|
5
|
+
}
|
6
|
+
ParameterMissing.prototype = new Error();
|
7
|
+
|
3
8
|
var defaults = {
|
4
9
|
prefix: 'PREFIX',
|
5
10
|
format: 'DEFAULT_FORMAT'
|
6
11
|
};
|
12
|
+
|
13
|
+
var NodeTypes = NODE_TYPES
|
7
14
|
|
8
15
|
var Utils = {
|
9
16
|
|
@@ -32,21 +39,8 @@
|
|
32
39
|
return path.replace(/\/+/g, "/").replace(/[\)\(]/g, "").replace(/\.$/m, '').replace(/\/$/m, '');
|
33
40
|
},
|
34
41
|
|
35
|
-
|
36
|
-
|
37
|
-
if (options.hasOwnProperty(name)) {
|
38
|
-
o = options[name];
|
39
|
-
delete options[name];
|
40
|
-
} else if (defaults.hasOwnProperty(name)) {
|
41
|
-
o = defaults[name];
|
42
|
-
}
|
43
|
-
return o;
|
44
|
-
},
|
45
|
-
|
46
|
-
extract_format: function(options) {
|
47
|
-
var format = options.hasOwnProperty("format") ? options.format : defaults.format;
|
48
|
-
delete options.format;
|
49
|
-
return format ? "." + format : "";
|
42
|
+
set_default_format: function(options) {
|
43
|
+
if (!options.hasOwnProperty("format")) options.format = defaults.format;
|
50
44
|
},
|
51
45
|
|
52
46
|
extract_anchor: function(options) {
|
@@ -74,49 +68,87 @@
|
|
74
68
|
}
|
75
69
|
},
|
76
70
|
|
77
|
-
|
71
|
+
clone: function (obj) {
|
72
|
+
if (null == obj || "object" != typeof obj) return obj;
|
73
|
+
var copy = obj.constructor();
|
74
|
+
for (var attr in obj) {
|
75
|
+
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
|
76
|
+
}
|
77
|
+
return copy;
|
78
|
+
},
|
79
|
+
|
80
|
+
prepare_parameters: function(required_parameters, actual_parameters, options) {
|
81
|
+
var result = this.clone(options);
|
82
|
+
for (var i=0; i < required_parameters.length; i++) {
|
83
|
+
result[required_parameters[i]] = actual_parameters[i];
|
84
|
+
}
|
85
|
+
return result;
|
86
|
+
},
|
87
|
+
|
88
|
+
build_path: function(required_parameters, route, args) {
|
78
89
|
args = Array.prototype.slice.call(args);
|
79
|
-
var
|
80
|
-
|
81
|
-
if (args.length > number_of_params) {
|
90
|
+
var opts = this.extract_options(required_parameters.length, args);
|
91
|
+
if (args.length > required_parameters.length) {
|
82
92
|
throw new Error("Too many parameters provided for path");
|
83
93
|
}
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
94
|
+
|
95
|
+
parameters = this.prepare_parameters(required_parameters, args, opts);
|
96
|
+
this.set_default_format(parameters);
|
97
|
+
var result = Utils.get_prefix();
|
98
|
+
var anchor = Utils.extract_anchor(parameters);
|
99
|
+
|
100
|
+
result += this.visit(route, parameters)
|
101
|
+
return Utils.clean_path(result + anchor) + Utils.serialize(parameters);
|
102
|
+
},
|
103
|
+
|
104
|
+
/*
|
105
|
+
* This function is JavaScript impelementation of the
|
106
|
+
* Journey::Visitors::Formatter that builds route by given parameters
|
107
|
+
* and parsed route binary tree.
|
108
|
+
* Binary tree is serialized in the following way:
|
109
|
+
* [node type, left node, right node ]
|
110
|
+
*/
|
111
|
+
visit: function(route, options) {
|
112
|
+
var type = route[0];
|
113
|
+
var left = route[1];
|
114
|
+
var right = route[2];
|
115
|
+
switch (type) {
|
116
|
+
case NodeTypes.GROUP:
|
117
|
+
try {
|
118
|
+
return this.visit(left, options);
|
119
|
+
} catch(e) {
|
120
|
+
if (e instanceof ParameterMissing) {
|
121
|
+
return "";
|
103
122
|
} else {
|
104
|
-
throw
|
123
|
+
throw e;
|
105
124
|
}
|
106
125
|
}
|
107
|
-
|
126
|
+
case NodeTypes.CAT:
|
127
|
+
return this.visit(left, options) + this.visit(right, options);
|
128
|
+
case NodeTypes.SYMBOL:
|
129
|
+
var value = options[left];
|
130
|
+
if (value) {
|
131
|
+
delete options[left];
|
132
|
+
return this.path_identifier(value);
|
133
|
+
} else {
|
134
|
+
throw new ParameterMissing("Route parameter missing: " + left);
|
135
|
+
}
|
136
|
+
/*
|
137
|
+
* I don't know what are these node types
|
138
|
+
* Please send your PR if you do
|
139
|
+
*/
|
140
|
+
//case NodeTypes.OR:
|
141
|
+
//case NodeTypes.STAR:
|
142
|
+
case NodeTypes.LITERAL:
|
143
|
+
return left;
|
144
|
+
case NodeTypes.SLASH:
|
145
|
+
return left;
|
146
|
+
case NodeTypes.DOT:
|
147
|
+
return left;
|
148
|
+
default:
|
149
|
+
throw new Error("Unknown Rails node type");
|
108
150
|
}
|
109
|
-
|
110
|
-
var anchor = Utils.extract_anchor(opts);
|
111
|
-
return Utils.clean_path(result + format + anchor) + Utils.serialize(opts);
|
112
|
-
},
|
113
|
-
|
114
|
-
specified: function(value) {
|
115
|
-
return !(value === undefined || value === null);
|
116
|
-
},
|
117
|
-
|
118
|
-
optional_part: function(part) {
|
119
|
-
return part.match(/\(/);
|
151
|
+
|
120
152
|
},
|
121
153
|
|
122
154
|
get_prefix: function(){
|
data/spec/js_routes_spec.rb
CHANGED
@@ -193,6 +193,12 @@ describe JsRoutes do
|
|
193
193
|
end
|
194
194
|
|
195
195
|
context "using optional path fragments" do
|
196
|
+
context "including not optional parts" do
|
197
|
+
it "should include everything that is not optional" do
|
198
|
+
evaljs("Routes.foo_path()").should == routes.foo_path
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
196
202
|
context "but not including them" do
|
197
203
|
it "should not include the optional parts" do
|
198
204
|
evaljs("Routes.things_path()").should == routes.things_path
|
@@ -7,7 +7,8 @@ describe "after Rails initialization" do
|
|
7
7
|
before(:all) do
|
8
8
|
|
9
9
|
FileUtils.rm_f(name)
|
10
|
-
JsRoutes.generate!(
|
10
|
+
JsRoutes.generate!(name)
|
11
|
+
|
11
12
|
|
12
13
|
Rails.application.initialize!
|
13
14
|
end
|
@@ -16,91 +17,74 @@ describe "after Rails initialization" do
|
|
16
17
|
FileUtils.rm_f(name)
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
File.exists?(name).should be_true
|
22
|
-
end
|
20
|
+
it "should generate routes file" do
|
21
|
+
File.exists?(name).should be_true
|
23
22
|
end
|
24
23
|
|
25
|
-
|
26
|
-
context "JsRoutes::Engine" do
|
24
|
+
context "JsRoutes::Engine" do
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
let(:test_asset_path) {
|
27
|
+
Rails.root.join('app','assets','javascripts','test.js')
|
28
|
+
}
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
after(:all) do
|
38
|
-
FileUtils.rm_f(test_asset_path)
|
30
|
+
before(:all) do
|
31
|
+
File.open(test_asset_path,'w') do |f|
|
32
|
+
f.puts "function() {}"
|
39
33
|
end
|
34
|
+
end
|
35
|
+
after(:all) do
|
36
|
+
FileUtils.rm_f(test_asset_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should have registered a preprocessor" do
|
40
|
+
pps = Rails.application.assets.preprocessors
|
41
|
+
js_pps = pps['application/javascript']
|
42
|
+
js_pps.map(&:name).should include('Sprockets::Processor (js-routes_dependent_on_routes)')
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
js_pps.map(&:name).should include('Sprockets::Processor (js-routes_dependent_on_routes)')
|
45
|
+
context "the preprocessor" do
|
46
|
+
before(:each) do
|
47
|
+
ctx.should_receive(:depend_on).with(Rails.root.join('config','routes.rb'))
|
45
48
|
end
|
49
|
+
let!(:ctx) do
|
50
|
+
Sprockets::Context.new(Rails.application.assets,
|
51
|
+
'js-routes.js',
|
52
|
+
Pathname.new('js-routes.js'))
|
46
53
|
|
47
|
-
|
48
|
-
|
49
|
-
ctx.should_receive(:depend_on).with(Rails.root.join('config','routes.rb'))
|
50
|
-
end
|
51
|
-
let!(:ctx) do
|
52
|
-
Sprockets::Context.new(Rails.application.assets,
|
53
|
-
'js-routes.js',
|
54
|
-
Pathname.new('js-routes.js'))
|
54
|
+
end
|
55
|
+
context "when dealing with js-routes.js" do
|
55
56
|
|
56
|
-
end
|
57
|
-
context "when dealing with js-routes.js" do
|
58
57
|
|
59
|
-
|
60
|
-
context
|
58
|
+
context "with Rails 3.1.1" do
|
59
|
+
context "and initialize on precompile" do
|
61
60
|
before(:each) do
|
62
|
-
Rails.
|
61
|
+
Rails.application.config.assets.initialize_on_precompile = true
|
63
62
|
end
|
64
|
-
|
65
63
|
it "should render some javascript" do
|
66
64
|
ctx.evaluate('js-routes.js').should =~ /window\.Routes/
|
67
65
|
end
|
68
66
|
end
|
69
|
-
|
70
|
-
context "with Rails 3.1.1" do
|
67
|
+
context "and not initialize on precompile" do
|
71
68
|
before(:each) do
|
72
|
-
Rails.
|
69
|
+
Rails.application.config.assets.initialize_on_precompile = false
|
73
70
|
end
|
74
|
-
|
75
|
-
|
76
|
-
Rails.application.config.assets.initialize_on_precompile = true
|
77
|
-
end
|
78
|
-
it "should render some javascript" do
|
79
|
-
ctx.evaluate('js-routes.js').should =~ /window\.Routes/
|
80
|
-
end
|
71
|
+
it "should raise an exception" do
|
72
|
+
lambda { ctx.evaluate('js-routes.js') }.should raise_error(/Cannot precompile/)
|
81
73
|
end
|
82
|
-
context "and not initialize on precompile" do
|
83
|
-
before(:each) do
|
84
|
-
Rails.application.config.assets.initialize_on_precompile = false
|
85
|
-
end
|
86
|
-
it "should raise an exception" do
|
87
|
-
lambda { ctx.evaluate('js-routes.js') }.should raise_error(/Cannot precompile/)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
74
|
end
|
75
|
+
|
92
76
|
end
|
77
|
+
end
|
93
78
|
|
94
79
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
80
|
+
end
|
81
|
+
context "when not dealing with js-routes.js" do
|
82
|
+
it "should not depend on routes.rb" do
|
83
|
+
ctx = Sprockets::Context.new(Rails.application.assets,
|
84
|
+
'test.js',
|
85
|
+
test_asset_path)
|
86
|
+
ctx.should_not_receive(:depend_on)
|
87
|
+
ctx.evaluate('test.js')
|
104
88
|
end
|
105
89
|
end
|
106
90
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -20,10 +20,8 @@ end
|
|
20
20
|
|
21
21
|
|
22
22
|
class App < Rails::Application
|
23
|
-
|
24
|
-
|
25
|
-
config.assets.enabled = true
|
26
|
-
end
|
23
|
+
# Enable the asset pipeline
|
24
|
+
config.assets.enabled = true
|
27
25
|
|
28
26
|
self.routes.draw do
|
29
27
|
resources :inboxes do
|
@@ -44,6 +42,8 @@ class App < Rails::Application
|
|
44
42
|
scope "(/optional/:optional_id)" do
|
45
43
|
resources :things
|
46
44
|
end
|
45
|
+
|
46
|
+
match "/other_optional/(:optional_id)" => "foo#foo", :as => :foo
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: js-routes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02
|
12
|
+
date: 2012-03-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &85230710 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '3.
|
21
|
+
version: '3.2'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *85230710
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: therubyracer
|
27
|
-
requirement: &
|
27
|
+
requirement: &85229560 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *85229560
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &85245130 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 2.7.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *85245130
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &85244440 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.0.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *85244440
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &85243690 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.6.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *85243690
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &85242750 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *85242750
|
80
80
|
description: Generates javascript file that defines all Rails named routes as javascript
|
81
81
|
helpers
|
82
82
|
email: agresso@gmail.com
|
@@ -119,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
119
|
version: '0'
|
120
120
|
segments:
|
121
121
|
- 0
|
122
|
-
hash:
|
122
|
+
hash: -314330307
|
123
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
124
|
none: false
|
125
125
|
requirements:
|