js-routes 0.7.5 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "rails", ">= 3.0"
3
+ gem "rails", ">= 3.2"
4
4
 
5
5
  group :development do
6
6
  gem "therubyracer"
data/Gemfile.lock CHANGED
@@ -1,37 +1,34 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- actionmailer (3.1.0)
5
- actionpack (= 3.1.0)
6
- mail (~> 2.3.0)
7
- actionpack (3.1.0)
8
- activemodel (= 3.1.0)
9
- activesupport (= 3.1.0)
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
- i18n (~> 0.6)
13
- rack (~> 1.3.2)
14
- rack-cache (~> 1.0.3)
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.0.0)
18
- activemodel (3.1.0)
19
- activesupport (= 3.1.0)
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
- i18n (~> 0.6)
23
- activerecord (3.1.0)
24
- activemodel (= 3.1.0)
25
- activesupport (= 3.1.0)
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.0)
29
- activemodel (= 3.1.0)
30
- activesupport (= 3.1.0)
31
- activesupport (3.1.0)
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 (2.2.1)
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.3.0)
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.16)
51
- multi_json (1.0.3)
52
- polyglot (0.3.2)
53
- rack (1.3.3)
54
- rack-cache (1.0.3)
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.0)
63
- actionmailer (= 3.1.0)
64
- actionpack (= 3.1.0)
65
- activerecord (= 3.1.0)
66
- activeresource (= 3.1.0)
67
- activesupport (= 3.1.0)
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.0)
70
- railties (3.1.0)
71
- actionpack (= 3.1.0)
72
- activesupport (= 3.1.0)
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.9.4)
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.0.0)
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.29)
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.0)
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
- ## JsRoutes
1
+ # JsRoutes
2
2
 
3
3
  Generates javascript file that defines all Rails named routes as javascript helpers
4
4
 
5
- ### Intallation
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
- Your application initializer, like `config/initializers/jsroutes.rb`:
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.generate!({
17
- #options
26
+ JsRoutes.setup do |config|
27
+ config.option = value
18
28
  })
19
29
  ```
20
30
 
21
31
  Available options:
22
32
 
23
- * `:file` - the file to generate the routes. Default:
24
- * `#{Rails.root}/app/assets/javascripts/routes.js` for Rails >= 3.1
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
- * `:include` - Array of regexps to include in js routes. Default: []
36
+ * `include` - Array of regexps to include in js routes. Default: []
30
37
  * Note that regexp applied to **named route** not to *URL*
31
- * `:namespace` - global object used to access routes. Default: `Routes`
38
+ * `namespace` - global object used to access routes. Default: `Routes`
32
39
  * Supports nested namespace like `MyProject.routes`
33
- * `:prefix` - String representing a url path to prepend to all paths
34
- * `Should be specified via :prefix => "/myprefix"`
40
+ * `prefix` - String representing a url path to prepend to all paths. Default: blank
41
+
42
+
43
+ ### Advanced Setup
35
44
 
36
- This is how you can generate separated routes files for different parts of application:
45
+ You can generate routes files on the application side like this:
37
46
 
38
47
  ``` ruby
39
- JsRoutes.generate!(:file => "#{path}/app_routes.js", :namespace => "AppRoutes", :exclude => /^admin_/, :default_format => "json")
40
- JsRoutes.generate!(:file => "#{path}/adm_routes.js", :namespace => "AdmRoutes", :include => /^admin_/, :default_format => "json")
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 routes to string and manipulate them yourself use:
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
- ### Usage
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
- ### What about security?
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
- ### Spork
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
- ### Advantages over alternatives
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.7.5
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.7.5"
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-13"
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.0"])
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.0"])
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.0"])
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 = if Rails.version >= "3.1"
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
- new(opts).generate!
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
- if Rails.version > "3.1.0" && !Rails.application.config.assets.initialize_on_precompile
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(@options[:file]), 'w') do |f|
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} => #{route_spec(route)}
113
- #{route.name}_path: function(#{(params + ["options"]).join(", ")}) {
114
- return Utils.build_path(#{params.size}, #{path_parts(route).inspect}, #{optional_params(route).inspect}, arguments)
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
- # TODO: might be possible to simplify this to use route.path
120
- # instead of all this path_info.source madness
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
- required_params(route).map do |name|
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
- end
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
- def route_spec route
155
- if Rails.version >= "3.2.0"
156
- route.path.spec
157
- else
158
- route.path
159
- end.to_s
160
- end
161
-
162
- def required_params(route)
163
- if Rails.version >= "3.2.0"
164
- return route.required_parts.map(&:to_s)
165
- end # if
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
@@ -1,4 +1,4 @@
1
- if defined?(Rails) && Rails.version >= "3.1"
1
+ if defined?(Rails)
2
2
  class JsRoutes
3
3
  class Engine < Rails::Engine
4
4
  JS_ROUTES_ASSET = 'js-routes'
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
- extract: function(name, options) {
36
- var o = undefined;
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
- build_path: function(number_of_params, parts, optional_params, args) {
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 result = Utils.get_prefix();
80
- var opts = Utils.extract_options(number_of_params, args);
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
- var params_count = 0, optional_params_count = 0;
85
- for (var i=0; i < parts.length; i++) {
86
- var part = parts[i];
87
- if (Utils.optional_part(part)) {
88
- var name = optional_params[optional_params_count];
89
- optional_params_count++;
90
- // try and find the option in opts
91
- var optional = Utils.extract(name, opts);
92
- if (Utils.specified(optional)) {
93
- result += part;
94
- result += Utils.path_identifier(optional);
95
- }
96
- } else {
97
- result += part;
98
- if (params_count < number_of_params) {
99
- params_count++;
100
- var value = args.shift();
101
- if (Utils.specified(value)) {
102
- result += Utils.path_identifier(value);
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 new Error("Insufficient parameters to build path");
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
- var format = Utils.extract_format(opts);
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(){
@@ -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!({:file => name})
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
- context '.generate!' do
20
- it "should generate routes file" do
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
- if Rails.version >= "3.1"
26
- context "JsRoutes::Engine" do
24
+ context "JsRoutes::Engine" do
27
25
 
28
- let(:test_asset_path) {
29
- Rails.root.join('app','assets','javascripts','test.js')
30
- }
26
+ let(:test_asset_path) {
27
+ Rails.root.join('app','assets','javascripts','test.js')
28
+ }
31
29
 
32
- before(:all) do
33
- File.open(test_asset_path,'w') do |f|
34
- f.puts "function() {}"
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
- it "should have registered a preprocessor" do
42
- pps = Rails.application.assets.preprocessors
43
- js_pps = pps['application/javascript']
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
- context "the preprocessor" do
48
- before(:each) do
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
- #TODO: check why doesn't work with let callbacks
60
- context 'with Rails 3.1.0' do
58
+ context "with Rails 3.1.1" do
59
+ context "and initialize on precompile" do
61
60
  before(:each) do
62
- Rails.stub!("version").and_return("3.1.0")
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.stub!("version").and_return("3.1.1")
69
+ Rails.application.config.assets.initialize_on_precompile = false
73
70
  end
74
- context "and initialize on precompile" do
75
- before(:each) do
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
- end
96
- context "when not dealing with js-routes.js" do
97
- it "should not depend on routes.rb" do
98
- ctx = Sprockets::Context.new(Rails.application.assets,
99
- 'test.js',
100
- test_asset_path)
101
- ctx.should_not_receive(:depend_on)
102
- ctx.evaluate('test.js')
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
- if Rails.version >= '3.1'
24
- # Enable the asset pipeline
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.7.5
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-13 00:00:00.000000000 Z
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: &20189100 !ruby/object:Gem::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.0'
21
+ version: '3.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *20189100
24
+ version_requirements: *85230710
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: therubyracer
27
- requirement: &20199080 !ruby/object:Gem::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: *20199080
35
+ version_requirements: *85229560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &20194300 !ruby/object:Gem::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: *20194300
46
+ version_requirements: *85245130
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &20205180 !ruby/object:Gem::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: *20205180
57
+ version_requirements: *85244440
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jeweler
60
- requirement: &20213600 !ruby/object:Gem::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: *20213600
68
+ version_requirements: *85243690
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rcov
71
- requirement: &20219180 !ruby/object:Gem::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: *20219180
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: 2245053018798616872
122
+ hash: -314330307
123
123
  required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  none: false
125
125
  requirements: