Skip to content

Instantly share code, notes, and snippets.

@sj26
Created April 10, 2013 03:53
Show Gist options
  • Save sj26/5351671 to your computer and use it in GitHub Desktop.
Save sj26/5351671 to your computer and use it in GitHub Desktop.
Generate rails-like route helpers for use in javascript land
class JourneyCoffeeGenerator < Journey::Visitors::Visitor
def accept node
@requirements = [[]]
super.gsub('" + "', '')
end
private
def visit_GROUP node
@requirements << []
inner = visit node.left
requirements = @requirements.pop
%{(if #{requirements.map { |key| "options.#{key}" }.join " or "} then (#{inner}) else "")}
end
def terminal node
# LITERAL or SLASH or DOT (SYMBOL handled below)
node.left.to_json
end
def binary node
[visit(node.left), visit(node.right)].join(' + ')
end
def nary node
node.children.map { |c| visit c }.join(' + ')
end
def visit_STAR node
@starred = true
super.tap do
@starred = false
end
end
def visit_SYMBOL node
key = node.to_sym
@requirements.last << key
%{(if options.#{key} then encodeURI#{"Component" unless @starred}(options.#{key}.toString()) else "")}
end
end
# Generate paths from rails route helpers in javascript land
app.routes =
named:
<% Rails.application.routes.named_routes.each do |name, route| %>
<%= name %>: [
<%= route.parts.to_json %>
<%= route.defaults.to_json %>
(options) ->
<%= JourneyCoffeeGenerator.new.accept(route.path.spec) %>
]
<% end %>
path_to: (name, params...) ->
# Grab the named route
[parts, defaults, generate] = tc.routes.named[name]
# The params may end with an options hash
options = (params.pop() if _.isObject(params[params.length - 1])) || {}
# Other positional parameters are route parts
_.extend options, _.object(parts.slice(0, params.length), params)
# Remove any default options, they're superfluous
delete options[param] if param is defaults[param] for param of options
# Generate a path
path = generate(options)
# Append a query if we have any non-part options
path += "?" + query if query = $.param(_(options).omit(parts...))
# Boom!
path
for name of tc.routes.named
tc.routes["#{name}_path"] = _.bind(tc.routes.path_to, name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment