js-routes 0.8.8 → 0.9.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/Readme.md CHANGED
@@ -61,6 +61,8 @@ Available options:
61
61
  * Default: blank
62
62
  * `camel_case` (version >= 0.8.8) - Generate camel case route names.
63
63
  * Default: false
64
+ * `url_links` (version >= 0.8.9) - Generate additional url links, where url_links value is beginning of url routes (ex: http[s]://example.com).
65
+ * Default: false
64
66
 
65
67
  You can generate routes files on the application side like this:
66
68
 
@@ -1,3 +1,3 @@
1
1
  class JsRoutes
2
- VERSION = "0.8.8"
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/js_routes.rb CHANGED
@@ -1,4 +1,6 @@
1
+ require 'uri'
1
2
  require 'js_routes/version'
3
+
2
4
  class JsRoutes
3
5
 
4
6
  #
@@ -12,7 +14,8 @@ class JsRoutes
12
14
  :exclude => [],
13
15
  :include => //,
14
16
  :file => DEFAULT_PATH,
15
- :prefix => "",
17
+ :prefix => nil,
18
+ :url_links => nil,
16
19
  :camel_case => false,
17
20
  :default_url_options => {}
18
21
  }
@@ -29,6 +32,8 @@ class JsRoutes
29
32
  :DOT => 8
30
33
  }
31
34
 
35
+ LAST_OPTIONS_KEY = "options".freeze
36
+
32
37
  class Options < Struct.new(*DEFAULTS.keys)
33
38
  def to_hash
34
39
  Hash[*members.zip(values).flatten(1)].symbolize_keys
@@ -89,7 +94,7 @@ class JsRoutes
89
94
  js = File.read(File.dirname(__FILE__) + "/routes.js")
90
95
  js.gsub!("NAMESPACE", @options[:namespace])
91
96
  js.gsub!("DEFAULT_URL_OPTIONS", json(@options[:default_url_options].merge(deprecated_default_format)))
92
- js.gsub!("PREFIX", @options[:prefix])
97
+ js.gsub!("PREFIX", @options[:prefix] || "")
93
98
  js.gsub!("NODE_TYPES", json(NODE_TYPES))
94
99
  js.gsub!("ROUTES", js_routes)
95
100
  end
@@ -148,19 +153,34 @@ class JsRoutes
148
153
  def build_js(route, parent_route)
149
154
  name = [parent_route.try(:name), route.name].compact
150
155
  parent_spec = parent_route.try(:path).try(:spec)
151
- required_parts = route.required_parts.clone
152
- optional_parts = route.optional_parts.clone
156
+ required_parts, optional_parts = route.required_parts.clone, route.optional_parts.clone
153
157
  optional_parts.push(required_parts.delete :format) if required_parts.include?(:format)
154
- route_name = "#{name.join('_')}_path"
155
- route_name = route_name.camelize(:lower) if true == @options[:camel_case]
158
+ route_name = generate_route_name(name)
159
+ url_link = generate_url_link(name, route_name, required_parts)
156
160
  _ = <<-JS.strip!
157
161
  // #{name.join('.')} => #{parent_spec}#{route.path.spec}
158
162
  #{route_name}: function(#{build_params(required_parts)}) {
163
+ if (!#{LAST_OPTIONS_KEY}){ #{LAST_OPTIONS_KEY} = {}; }
159
164
  return Utils.build_path(#{json(required_parts)}, #{json(optional_parts)}, #{json(serialize(route.path.spec, parent_spec))}, arguments);
160
- }
165
+ }#{",\n" + url_link if url_link.length > 0}
161
166
  JS
162
167
  end
163
168
 
169
+ def generate_url_link(name, route_name, required_parts)
170
+ return "" unless @options[:url_links]
171
+ raise "invalid URL format in url_links (ex: http[s]://example.com)" if @options[:url_links].match(URI::regexp(%w(http https))).nil?
172
+ _ = <<-JS.strip!
173
+ #{generate_route_name(name, true)}: function(#{build_params(required_parts)}) {
174
+ return "" + #{@options[:url_links].inspect} + this.#{route_name}(#{build_params(required_parts)});
175
+ }
176
+ JS
177
+ end
178
+
179
+ def generate_route_name(name, is_url = false)
180
+ route_name = "#{name.join('_')}_#{is_url ? "url" : "path"}"
181
+ @options[:camel_case] ? route_name.camelize(:lower) : route_name
182
+ end
183
+
164
184
  def json(string)
165
185
  self.class.json(string)
166
186
  end
@@ -169,8 +189,8 @@ class JsRoutes
169
189
  params = required_parts.map do |name|
170
190
  # prepending each parameter name with underscore
171
191
  # to prevent conflict with JS reserved words
172
- "_" + name.to_s
173
- end << "options"
192
+ "_#{name}"
193
+ end << LAST_OPTIONS_KEY
174
194
  params.join(", ")
175
195
  end
176
196
 
data/lib/routes.js CHANGED
@@ -24,14 +24,14 @@
24
24
  }
25
25
  if (window.jQuery) {
26
26
  result = window.jQuery.param(obj);
27
- return (!result ? "" : "?" + result);
27
+ return (!result ? "" : result);
28
28
  }
29
29
  s = [];
30
30
  for (key in obj) {
31
31
  if (!__hasProp.call(obj, key)) continue;
32
32
  prop = obj[key];
33
33
  if (prop != null) {
34
- if (prop instanceof Array) {
34
+ if (this.getObjectType(prop) === "array") {
35
35
  for (i = _i = 0, _len = prop.length; _i < _len; i = ++_i) {
36
36
  val = prop[i];
37
37
  s.push("" + key + (encodeURIComponent("[]")) + "=" + (encodeURIComponent(val.toString())));
@@ -44,7 +44,7 @@
44
44
  if (!s.length) {
45
45
  return "";
46
46
  }
47
- return "?" + (s.join("&"));
47
+ return s.join("&");
48
48
  },
49
49
  clean_path: function(path) {
50
50
  var last_index;
@@ -74,7 +74,7 @@
74
74
  anchor = "";
75
75
  if (options.hasOwnProperty("anchor")) {
76
76
  anchor = "#" + options.anchor;
77
- options.anchor = null;
77
+ delete options.anchor;
78
78
  }
79
79
  return anchor;
80
80
  },
@@ -82,7 +82,7 @@
82
82
  var ret_value;
83
83
 
84
84
  ret_value = {};
85
- if (args.length > number_of_params && typeof args[args.length - 1] === "object") {
85
+ if (args.length > number_of_params && this.getObjectType(args[args.length - 1]) === "object") {
86
86
  ret_value = args.pop();
87
87
  }
88
88
  return ret_value;
@@ -97,9 +97,9 @@
97
97
  return "";
98
98
  }
99
99
  property = object;
100
- if (typeof object === "object") {
100
+ if (this.getObjectType(object) === "object") {
101
101
  property = object.to_param || object.id || object;
102
- if (typeof property === "function") {
102
+ if (this.getObjectType(property) === "function") {
103
103
  property = property.call(object);
104
104
  }
105
105
  }
@@ -108,7 +108,7 @@
108
108
  clone: function(obj) {
109
109
  var attr, copy, key;
110
110
 
111
- if (null === obj || "object" !== typeof obj) {
111
+ if ((obj == null) || "object" !== this.getObjectType(obj)) {
112
112
  return obj;
113
113
  }
114
114
  copy = obj.constructor();
@@ -130,7 +130,7 @@
130
130
  return result;
131
131
  },
132
132
  build_path: function(required_parameters, optional_parts, route, args) {
133
- var opts, parameters, result;
133
+ var opts, parameters, result, url, url_params;
134
134
 
135
135
  args = Array.prototype.slice.call(args);
136
136
  opts = this.extract_options(required_parameters.length, args);
@@ -139,17 +139,25 @@
139
139
  }
140
140
  parameters = this.prepare_parameters(required_parameters, args, opts);
141
141
  this.set_default_url_options(optional_parts, parameters);
142
- result = "" + (Utils.get_prefix()) + (this.visit(route, parameters));
143
- return Utils.clean_path("" + result + (Utils.extract_anchor(parameters))) + Utils.serialize(parameters);
142
+ result = "" + (this.get_prefix()) + (this.visit(route, parameters));
143
+ url = Utils.clean_path("" + result + (this.extract_anchor(parameters)));
144
+ if ((url_params = this.serialize(parameters)).length) {
145
+ url += "?" + url_params;
146
+ }
147
+ return url;
144
148
  },
145
149
  visit: function(route, parameters, optional) {
146
150
  var left, left_part, right, right_part, type, value;
147
151
 
152
+ if (optional == null) {
153
+ optional = false;
154
+ }
148
155
  type = route[0], left = route[1], right = route[2];
149
156
  switch (type) {
150
157
  case NodeTypes.GROUP:
151
- case NodeTypes.STAR:
152
158
  return this.visit(left, parameters, true);
159
+ case NodeTypes.STAR:
160
+ return this.visit_globbing(left, parameters, true);
153
161
  case NodeTypes.LITERAL:
154
162
  case NodeTypes.SLASH:
155
163
  case NodeTypes.DOT:
@@ -164,7 +172,7 @@
164
172
  case NodeTypes.SYMBOL:
165
173
  value = parameters[left];
166
174
  if (value != null) {
167
- parameters[left] = null;
175
+ delete parameters[left];
168
176
  return this.path_identifier(value);
169
177
  }
170
178
  if (optional) {
@@ -177,6 +185,24 @@
177
185
  throw new Error("Unknown Rails node type");
178
186
  }
179
187
  },
188
+ visit_globbing: function(route, parameters, optional) {
189
+ var left, right, type, value;
190
+
191
+ type = route[0], left = route[1], right = route[2];
192
+ value = parameters[left];
193
+ if (value == null) {
194
+ return this.visit(route, parameters, optional);
195
+ }
196
+ parameters[left] = (function() {
197
+ switch (this.getObjectType(value)) {
198
+ case "array":
199
+ return value.join("/");
200
+ default:
201
+ return value;
202
+ }
203
+ }).call(this);
204
+ return this.visit(route, parameters, optional);
205
+ },
180
206
  get_prefix: function() {
181
207
  var prefix;
182
208
 
@@ -186,6 +212,30 @@
186
212
  }
187
213
  return prefix;
188
214
  },
215
+ _classToTypeCache: null,
216
+ _classToType: function() {
217
+ var name, _i, _len, _ref;
218
+
219
+ if (this._classToTypeCache != null) {
220
+ return this._classToTypeCache;
221
+ }
222
+ this._classToTypeCache = {};
223
+ _ref = "Boolean Number String Function Array Date RegExp Undefined Null".split(" ");
224
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
225
+ name = _ref[_i];
226
+ this._classToTypeCache["[object " + name + "]"] = name.toLowerCase();
227
+ }
228
+ return this._classToTypeCache;
229
+ },
230
+ getObjectType: function(obj) {
231
+ var strType;
232
+
233
+ if (window.jQuery && (window.jQuery.type != null)) {
234
+ return window.jQuery.type(obj);
235
+ }
236
+ strType = Object.prototype.toString.call(obj);
237
+ return this._classToType()[strType] || "object";
238
+ },
189
239
  namespace: function(root, namespaceString) {
190
240
  var current, parts;
191
241
 
data/lib/routes.js.coffee CHANGED
@@ -6,21 +6,21 @@ defaults =
6
6
 
7
7
  NodeTypes = NODE_TYPES
8
8
  Utils =
9
+
9
10
  serialize: (obj) ->
10
11
  return "" unless obj
11
12
  if window.jQuery
12
13
  result = window.jQuery.param(obj)
13
- return (if not result then "" else "?#{result}")
14
+ return (if not result then "" else result)
14
15
  s = []
15
- for own key, prop of obj
16
- if prop?
17
- if prop instanceof Array
18
- for val, i in prop
19
- s.push "#{key}#{encodeURIComponent("[]")}=#{encodeURIComponent(val.toString())}"
20
- else
21
- s.push "#{key}=#{encodeURIComponent(prop.toString())}"
16
+ for own key, prop of obj when prop?
17
+ if @getObjectType(prop) is "array"
18
+ for val, i in prop
19
+ s.push "#{key}#{encodeURIComponent("[]")}=#{encodeURIComponent(val.toString())}"
20
+ else
21
+ s.push "#{key}=#{encodeURIComponent(prop.toString())}"
22
22
  return "" unless s.length
23
- "?#{s.join("&")}"
23
+ s.join("&")
24
24
 
25
25
  clean_path: (path) ->
26
26
  path = path.split("://")
@@ -37,12 +37,12 @@ Utils =
37
37
  anchor = ""
38
38
  if options.hasOwnProperty("anchor")
39
39
  anchor = "##{options.anchor}"
40
- options.anchor = null
40
+ delete options.anchor
41
41
  anchor
42
42
 
43
43
  extract_options: (number_of_params, args) ->
44
44
  ret_value = {}
45
- if args.length > number_of_params and typeof (args[args.length - 1]) is "object"
45
+ if args.length > number_of_params and @getObjectType(args[args.length - 1]) is "object"
46
46
  ret_value = args.pop()
47
47
  ret_value
48
48
 
@@ -51,13 +51,13 @@ Utils =
51
51
  # null, undefined, false or ''
52
52
  return "" unless object
53
53
  property = object
54
- if typeof (object) is "object"
54
+ if @getObjectType(object) is "object"
55
55
  property = object.to_param or object.id or object
56
- property = property.call(object) if typeof (property) is "function"
56
+ property = property.call(object) if @getObjectType(property) is "function"
57
57
  property.toString()
58
58
 
59
59
  clone: (obj) ->
60
- return obj if null is obj or "object" isnt typeof obj
60
+ return obj if !obj? or "object" isnt @getObjectType(obj)
61
61
  copy = obj.constructor()
62
62
  copy[key] = attr for own key, attr of obj
63
63
  copy
@@ -73,8 +73,10 @@ Utils =
73
73
  throw new Error("Too many parameters provided for path") if args.length > required_parameters.length
74
74
  parameters = @prepare_parameters(required_parameters, args, opts)
75
75
  @set_default_url_options optional_parts, parameters
76
- result = "#{Utils.get_prefix()}#{@visit(route, parameters)}"
77
- Utils.clean_path("#{result}#{Utils.extract_anchor(parameters)}") + Utils.serialize(parameters)
76
+ result = "#{@get_prefix()}#{@visit(route, parameters)}"
77
+ url = Utils.clean_path("#{result}#{@extract_anchor(parameters)}")
78
+ url += "?#{url_params}" if (url_params = @serialize(parameters)).length
79
+ url
78
80
  #
79
81
  # This function is JavaScript impelementation of the
80
82
  # Journey::Visitors::Formatter that builds route by given parameters
@@ -86,11 +88,13 @@ Utils =
86
88
  # If set to `true`, this method will not throw when encountering
87
89
  # a missing parameter (used in recursive calls).
88
90
  #
89
- visit: (route, parameters, optional) ->
91
+ visit: (route, parameters, optional = false) ->
90
92
  [type, left, right] = route
91
93
  switch type
92
- when NodeTypes.GROUP, NodeTypes.STAR
94
+ when NodeTypes.GROUP
93
95
  @visit left, parameters, true
96
+ when NodeTypes.STAR
97
+ @visit_globbing left, parameters, true
94
98
  when NodeTypes.LITERAL, NodeTypes.SLASH, NodeTypes.DOT
95
99
  left
96
100
  when NodeTypes.CAT
@@ -101,7 +105,7 @@ Utils =
101
105
  when NodeTypes.SYMBOL
102
106
  value = parameters[left]
103
107
  if value?
104
- parameters[left] = null
108
+ delete parameters[left]
105
109
  return @path_identifier(value)
106
110
  if optional
107
111
  "" # missing parameter
@@ -115,11 +119,65 @@ Utils =
115
119
  else
116
120
  throw new Error("Unknown Rails node type")
117
121
 
122
+ #
123
+ # This method convert value for globbing in right value for rails route
124
+ #
125
+ visit_globbing: (route, parameters, optional) ->
126
+ [type, left, right] = route
127
+ value = parameters[left]
128
+ return @visit(route, parameters, optional) unless value?
129
+ parameters[left] = switch @getObjectType(value)
130
+ when "array"
131
+ value.join("/")
132
+ else
133
+ value
134
+ @visit route, parameters, optional
135
+
136
+ #
137
+ # This method check and return prefix from options
138
+ #
118
139
  get_prefix: ->
119
140
  prefix = defaults.prefix
120
141
  prefix = (if prefix.match("/$") then prefix else "#{prefix}/") if prefix isnt ""
121
142
  prefix
122
143
 
144
+ #
145
+ # This is helper method to define object type.
146
+ # The typeof operator is probably the biggest design flaw of JavaScript, simply because it's basically completely broken.
147
+ #
148
+ # Value Class Type
149
+ # -------------------------------------
150
+ # "foo" String string
151
+ # new String("foo") String object
152
+ # 1.2 Number number
153
+ # new Number(1.2) Number object
154
+ # true Boolean boolean
155
+ # new Boolean(true) Boolean object
156
+ # new Date() Date object
157
+ # new Error() Error object
158
+ # [1,2,3] Array object
159
+ # new Array(1, 2, 3) Array object
160
+ # new Function("") Function function
161
+ # /abc/g RegExp object
162
+ # new RegExp("meow") RegExp object
163
+ # {} Object object
164
+ # new Object() Object object
165
+ #
166
+ # What is why I use Object.prototype.toString() to know better type of variable. Or use jQuery.type, if it available.
167
+ # _classToTypeCache used for perfomance cache of types map (underscore at the beginning mean private method - of course it doesn't realy private).
168
+ #
169
+ _classToTypeCache: null
170
+ _classToType: ->
171
+ return @_classToTypeCache if @_classToTypeCache?
172
+ @_classToTypeCache = {}
173
+ for name in "Boolean Number String Function Array Date RegExp Undefined Null".split(" ")
174
+ @_classToTypeCache["[object " + name + "]"] = name.toLowerCase()
175
+ @_classToTypeCache
176
+ getObjectType: (obj) ->
177
+ return window.jQuery.type(obj) if window.jQuery and window.jQuery.type?
178
+ strType = Object::toString.call(obj)
179
+ @_classToType()[strType] or "object"
180
+
123
181
  namespace: (root, namespaceString) ->
124
182
  parts = (if namespaceString then namespaceString.split(".") else [])
125
183
  return unless parts.length
@@ -129,4 +187,4 @@ Utils =
129
187
 
130
188
  Utils.namespace window, "NAMESPACE"
131
189
  window.NAMESPACE = ROUTES
132
- window.NAMESPACE.options = defaults
190
+ window.NAMESPACE.options = defaults
@@ -172,4 +172,51 @@ describe JsRoutes, "options" do
172
172
  end
173
173
  end
174
174
  end
175
+
176
+ describe "url_links" do
177
+ context "with default option" do
178
+ let(:_options) { Hash.new }
179
+ it "should generate only path links" do
180
+ evaljs("Routes.inbox_path(1)").should == routes.inbox_path(1)
181
+ evaljs("Routes.inbox_url").should be_nil
182
+ end
183
+ end
184
+
185
+ context "with host" do
186
+ let(:_options) { { :url_links => "http://localhost" } }
187
+ it "should generate path and url links" do
188
+ evaljs("Routes.inbox_path").should_not be_nil
189
+ evaljs("Routes.inbox_url").should_not be_nil
190
+ evaljs("Routes.inbox_path(1)").should == routes.inbox_path(1)
191
+ evaljs("Routes.inbox_url(1)").should == "http://localhost#{routes.inbox_path(1)}"
192
+ evaljs("Routes.inbox_url(1, { test_key: \"test_val\" })").should == "http://localhost#{routes.inbox_path(1, :test_key => "test_val")}"
193
+ end
194
+ end
195
+
196
+ context "with invalid host" do
197
+ it "should raise error" do
198
+ expect { JsRoutes.generate({ :url_links => "localhost" }) }.to raise_error RuntimeError
199
+ end
200
+ end
201
+
202
+ context "with host and camel_case" do
203
+ let(:_options) { { :camel_case => true, :url_links => "http://localhost" } }
204
+ it "should generate path and url links" do
205
+ evaljs("Routes.inboxPath").should_not be_nil
206
+ evaljs("Routes.inboxUrl").should_not be_nil
207
+ evaljs("Routes.inboxPath(1)").should == routes.inbox_path(1)
208
+ evaljs("Routes.inboxUrl(1)").should == "http://localhost#{routes.inbox_path(1)}"
209
+ end
210
+ end
211
+
212
+ context "with host and prefix" do
213
+ let(:_options) { { :prefix => "/api", :url_links => "https://example.com" } }
214
+ it "should generate path and url links" do
215
+ evaljs("Routes.inbox_path").should_not be_nil
216
+ evaljs("Routes.inbox_url").should_not be_nil
217
+ evaljs("Routes.inbox_path(1)").should == "/api#{routes.inbox_path(1)}"
218
+ evaljs("Routes.inbox_url(1)").should == "https://example.com/api#{routes.inbox_path(1)}"
219
+ end
220
+ end
221
+ end
175
222
  end
@@ -76,14 +76,28 @@ describe JsRoutes, "compatibility with Rails" do
76
76
  evaljs("Routes.book_path('thrillers', 1)").should == routes.book_path('thrillers', 1)
77
77
  end
78
78
 
79
- it "should support routes globbing as hash" do
80
- pending
81
- evaljs("Routes.book_path(1, {section: 'thrillers'})").should == routes.book_path(1, :section => 'thrillers')
79
+ it "should support routes globbing as array" do
80
+ evaljs("Routes.book_path(['thrillers'], 1)").should == routes.book_path(['thrillers'], 1)
81
+ end
82
+
83
+ it "should bee support routes globbing as array" do
84
+ evaljs("Routes.book_path([1, 2, 3], 1)").should == routes.book_path([1, 2, 3], 1)
82
85
  end
83
86
 
84
87
  it "should bee support routes globbing as hash" do
85
- pending
86
- evaljs("Routes.book_path(1)").should == routes.book_path(1)
88
+ evaljs("Routes.book_path('a_test/b_test/c_test', 1)").should == routes.book_path('a_test/b_test/c_test', 1)
89
+ end
90
+
91
+ it "should support routes globbing as array with optional params" do
92
+ evaljs("Routes.book_path([1, 2, 3, 5], 1, {c: '1'})").should == routes.book_path([1, 2, 3, 5], 1, { :c => "1" })
93
+ end
94
+
95
+ it "should support routes globbing in book_title route as array" do
96
+ evaljs("Routes.book_title_path('john', ['thrillers', 'comedian'])").should == routes.book_title_path('john', ['thrillers', 'comedian'])
97
+ end
98
+
99
+ it "should support routes globbing in book_title route as array with optional params" do
100
+ evaljs("Routes.book_title_path('john', ['thrillers', 'comedian'], {some_key: 'some_value'})").should == routes.book_title_path('john', ['thrillers', 'comedian'], {:some_key => 'some_value'})
87
101
  end
88
102
  end
89
103
 
@@ -98,6 +112,7 @@ describe JsRoutes, "compatibility with Rails" do
98
112
  it "should support serialization of objects" do
99
113
  evaljs("window.jQuery.param(#{_value.to_json})").should == _value.to_param
100
114
  evaljs("Routes.inboxes_path(#{_value.to_json})").should == routes.inboxes_path(_value)
115
+ evaljs("Routes.inbox_path(1, #{_value.to_json})").should == routes.inbox_path(1, _value)
101
116
  end
102
117
  end
103
118
  context "when parameters is a hash" do
@@ -202,5 +217,25 @@ describe JsRoutes, "compatibility with Rails" do
202
217
  "Routes.inbox_message_path({id:1, to_param: 'my'}, {id:2}, {custom: true, format: 'json'})"
203
218
  ).should == routes.inbox_message_path(inbox, 2, :custom => true, :format => "json")
204
219
  end
220
+
221
+ context "when globbing" do
222
+ it "should prefer to_param property over id property" do
223
+ evaljs("Routes.book_path({id: 1, to_param: 'my'}, 1)").should == routes.book_path(inbox, 1)
224
+ end
225
+
226
+ it "should call to_param if it is a function" do
227
+ evaljs("Routes.book_path({id: 1, to_param: function(){ return 'my';}}, 1)").should == routes.book_path(inbox, 1)
228
+ end
229
+
230
+ it "should call id if it is a function" do
231
+ evaljs("Routes.book_path({id: function() { return 'technical';}}, 1)").should == routes.book_path('technical', 1)
232
+ end
233
+
234
+ it "should support options argument" do
235
+ evaljs(
236
+ "Routes.book_path({id:1, to_param: 'my'}, {id:2}, {custom: true, format: 'json'})"
237
+ ).should == routes.book_path(inbox, 2, :custom => true, :format => "json")
238
+ end
239
+ end
205
240
  end
206
241
  end
data/spec/spec_helper.rb CHANGED
@@ -68,6 +68,7 @@ def draw_routes
68
68
  match "/other_optional/(:optional_id)" => "foo#foo", :as => :foo
69
69
 
70
70
  match 'books/*section/:title' => 'books#show', :as => :book
71
+ match 'books/:title/*section' => 'books#show', :as => :book_title
71
72
 
72
73
  mount BlogEngine::Engine => "/blog", :as => :blog_app
73
74
 
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.8.8
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -169,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
169
  version: '0'
170
170
  segments:
171
171
  - 0
172
- hash: -1021076515432540813
172
+ hash: 1949067975122087130
173
173
  required_rubygems_version: !ruby/object:Gem::Requirement
174
174
  none: false
175
175
  requirements: