Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routes path specs #135

Merged
merged 6 commits into from
Dec 17, 2014
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## master

* Add the compact mode [#125](https://github.com/railsware/js-routes/pull/125)
* Add support for host, protocol, and port configuration [#137](https://github.com/railsware/js-routes/pull/137)
* Routes path specs [#135](https://github.com/railsware/js-routes/pull/135)

## v0.9.9

* Bugfix Rails Engine subapplication route generation when they are nested [#120](https://github.com/railsware/js-routes/pull/120)
Expand Down
8 changes: 7 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# JsRoutes
[![Build Status](https://travis-ci.org/railsware/js-routes.png)](https://travis-ci.org/railsware/js-routes)
[![Build Status](https://travis-ci.org/railsware/js-routes.svg?branch=master)](https://travis-ci.org/railsware/js-routes)

Generates javascript file that defines all Rails named routes as javascript helpers

Expand Down Expand Up @@ -111,7 +111,13 @@ JsRoutes.generate!("#{path}/api_routes.js", :namespace => "ApiRoutes", :include
Configuration above will create a nice javascript file with `Routes` object that has all the rails routes available:

``` js
'' + Routes.users_path // => "/users(.:format)", a string representation of the object
Routes.users_path.toString() // => "/users(.:format)"
Routes.users_path.required_params // => []
Routes.users_path() // => "/users"
'' + Routes.user_path // => "/users/:id(.:format)"
Routes.user_path.toString() // => "/users/:id(.:format)"
Routes.user_path.required_params // => ['id']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are advanced things. Lets extract them to its own part of readme.

Don't want tricky features to be mixed with core.

Routes.user_path(1) // => "/users/1"
Routes.user_path(1, {format: 'json'}) // => "/users/1.json"
Routes.new_user_project_path(1, {format: 'json'}) // => "/users/1/projects/new.json"
Expand Down
7 changes: 3 additions & 4 deletions lib/js_routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,8 @@ def build_js(route, parent_route)
url_link = generate_url_link(name, route_name, required_parts, route)
_ = <<-JS.strip!
// #{name.join('.')} => #{parent_spec}#{route.path.spec}
#{route_name}: function(#{build_params(required_parts)}) {
return Utils.build_path(#{json(required_parts)}, #{json(optional_parts)}, #{json(serialize(route.path.spec, parent_spec))}, arguments);
}#{",\n" + url_link if url_link.length > 0}
// function(#{[required_parts, LAST_OPTIONS_KEY].flatten.join(', ')})
#{route_name}: Utils.route(#{json(required_parts)}, #{json(optional_parts)}, #{json(serialize(route.path.spec, parent_spec))}, arguments)#{",\n" + url_link if url_link.length > 0}
JS
end

Expand Down Expand Up @@ -204,7 +203,7 @@ def json(string)
self.class.json(string)
end

def build_params required_parts
def build_params(required_parts)
params = required_parts.map do |name|
# prepending each parameter name with underscore
# to prevent conflict with JS reserved words
Expand Down
39 changes: 39 additions & 0 deletions lib/routes.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions lib/routes.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,29 @@ Utils =
else
throw new Error("Unknown Rails node type")

#
# This method build spec for route
#
build_path_spec: (route, wildcard=false) ->
[type, left, right] = route
switch type
when NodeTypes.GROUP
"(#{@build_path_spec(left)})"
when NodeTypes.CAT
"#{@build_path_spec(left)}#{@build_path_spec(right)}"
when NodeTypes.STAR
@build_path_spec(left, true)
when NodeTypes.SYMBOL
if wildcard is true
"#{if left[0] is '*' then '' else '*'}#{left}"
else
":#{left}"
when NodeTypes.SLASH, NodeTypes.DOT, NodeTypes.LITERAL
left
# Not sure about this one
# when NodeTypes.OR
else throw new Error("Unknown Rails node type")

#
# This method convert value for globbing in right value for rails route
#
Expand All @@ -191,6 +214,15 @@ Utils =
prefix = (if prefix.match("/$") then prefix else "#{prefix}/") if prefix isnt ""
prefix

#
# route function: create route path function and add spec to it
#
route: (required_parts, optional_parts, route_spec) ->
path_fn = -> Utils.build_path(required_parts, optional_parts, route_spec, arguments)
path_fn.required_params = required_parts
path_fn.toString = -> Utils.build_path_spec(route_spec)
path_fn

#
# This is helper method to define object type.
# The typeof operator is probably the biggest design flaw of JavaScript, simply because it's basically completely broken.
Expand Down
18 changes: 14 additions & 4 deletions spec/js_routes/generated_javascript_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,24 @@

describe "generated js" do
subject { JsRoutes.generate }
it "should call route function for each route" do
is_expected.to include("inboxes_path: Utils.route(")
end
it "should have correct function without arguments signature" do
is_expected.to include("inboxes_path: function(options)")
is_expected.to include("inboxes_path: Utils.route([]")
end
it "should have correct function with arguments signature" do
is_expected.to include("inbox_message_path: function(_inbox_id, _id, options)")
is_expected.to include("inbox_message_path: Utils.route([\"inbox_id\",\"id\"]")
end
it "should have correct function signature with unordered hash" do
is_expected.to include("inbox_message_attachment_path: function(_inbox_id, _message_id, _id, options)")
is_expected.to include("inbox_message_attachment_path: Utils.route([\"inbox_id\",\"message_id\",\"id\"]")
end

it "should have correct function comment with options argument" do
is_expected.to include("// function(options)\n inboxes_path: Utils.route")
end
it "should have correct function comment with arguments" do
is_expected.to include("// function(inbox_id, message_id, options)\n new_inbox_message_attachment_path: Utils.route")
end

it "routes should be sorted in alphabetical order" do
Expand Down Expand Up @@ -51,7 +61,7 @@
describe "compiled javascript asset" do
subject { ERB.new(File.read("app/assets/javascripts/js-routes.js.erb")).result(binding) }
it "should have js routes code" do
is_expected.to include("inbox_message_path: function(_inbox_id, _id, options)")
is_expected.to include("inbox_message_path: Utils.route([\"inbox_id\",\"id\"]")
end
end
end
28 changes: 28 additions & 0 deletions spec/js_routes/rails_routes_compatibility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,32 @@
end
end
end

context "when specs" do
it "should show inbox spec" do
expect(evaljs("Routes.inbox_path.toString()")).to eq('/inboxes/:id(.:format)')
end

it "should show inbox spec convert to string" do
expect(evaljs("'' + Routes.inbox_path")).to eq('/inboxes/:id(.:format)')
end

it "should show inbox message spec" do
expect(evaljs("Routes.inbox_message_path.toString()")).to eq('/inboxes/:inbox_id/messages/:id(.:format)')
end

it "should show inbox message spec convert to string" do
expect(evaljs("'' + Routes.inbox_message_path")).to eq('/inboxes/:inbox_id/messages/:id(.:format)')
end
end

context "when params" do
it "should show inbox spec" do
expect(evaljs("Routes.inbox_path.required_params").to_a).to eq(["id"])
end

it "should show inbox message spec" do
expect(evaljs("Routes.inbox_message_path.required_params").to_a).to eq(["inbox_id", "id"])
end
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test for function comment as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. Waiting travis :)