asset_pipeline_routes 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +12 -7
- data/lib/asset_pipeline_routes.rb +8 -7
- data/lib/asset_pipeline_routes/js_function_helper.rb +1 -0
- data/lib/asset_pipeline_routes/path.rb +51 -0
- data/lib/asset_pipeline_routes/routes.rb +34 -0
- data/lib/asset_pipeline_routes/routes_context.rb +2 -3
- data/lib/asset_pipeline_routes/version.rb +2 -1
- data/spec/asset_pipeline_routes_spec.rb +31 -13
- data/spec/path_spec.rb +32 -0
- data/spec/spec_helper.rb +2 -1
- metadata +12 -10
- data/lib/asset_pipeline_routes/routes_helper.rb +0 -26
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Getting your Rails routes into the Rails 3.2 asset pipeline is really easy. Just
|
4
4
|
`include Rails.application.routes.url_helpers` and you have all your routes available.
|
5
5
|
|
6
|
-
But except for hard-coded links this won't help you, because
|
6
|
+
But except for hard-coded links this won't help you, because in production you have to pass in resource parameters at compile-time, where they are not available.
|
7
7
|
|
8
8
|
Heh, you might think! Just call a route helper and pass in a dynamic parameter mapping, like
|
9
9
|
`user_path('{{id}}')`. Sadly this won't yield the desired result! Instead of `/users/{{id}}`, you'll be presented with `/users/%7B%7Bid%7D%7D` because you're mapping just got html_escaped!
|
@@ -21,25 +21,30 @@ Here's an example, assuming you got a routes.rb with
|
|
21
21
|
resources :users # => yields multiple routes, e.g. /users/:id(.:format)
|
22
22
|
|
23
23
|
in it. Then, in you're javascript file you'd call `r.users_path`. All path fragments are replaced with Mustache-style attribute bindings by default:
|
24
|
-
|
24
|
+
|
25
25
|
# application.js.coffee.erb
|
26
26
|
userPath = '<%= r.user_path %>' # => yields /users/{{id}}
|
27
27
|
usersPath = '<%= r.users_path %>' # => yields /users
|
28
28
|
|
29
29
|
You can even hook up member- or collection routes, whatever you like really. Just prefix your routes with `r.` and you can directly use them in your asset-pipeline!
|
30
30
|
|
31
|
-
All `_path`-methods take an arbitrary argument which is used to evaluate the final route.
|
31
|
+
All `_path`-methods take an arbitrary argument which is used to evaluate the final route.
|
32
32
|
So if you want a regexp matching all users-show actions, you can do it just like this:
|
33
33
|
|
34
34
|
# application.js.coffee.erb
|
35
35
|
usersPath = '<%= r.user_path '\d+' %>' # => yields /users/\d+
|
36
|
-
|
36
|
+
|
37
37
|
Sometimes you want to generate the URL for a given resource on the client-side entirely. That's possible as well:
|
38
38
|
|
39
|
+
# application.js.erb
|
40
|
+
var editUserRoute = <%= r.edit_user_path_method %>; // => yields anonymous function in js
|
41
|
+
var editUserPath = editUserRoute(42); // => yields '/users/42/edit'
|
42
|
+
|
43
|
+
# or, if you prefer CoffeeScript:
|
39
44
|
# application.js.coffee.erb
|
40
|
-
|
41
|
-
editUserPath = editUserRoute(42) # => yields /users/42/edit
|
42
|
-
|
45
|
+
editUserPath = <%= r.edit_user_path_method(:coffee) %>
|
46
|
+
editUserPath = editUserRoute(42) # => yields '/users/42/edit'
|
47
|
+
|
43
48
|
Now you have total control over your Rails routes.
|
44
49
|
|
45
50
|
# Addendum
|
@@ -1,16 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require_relative "asset_pipeline_routes/version"
|
2
|
-
require_relative "asset_pipeline_routes/
|
3
|
+
require_relative "asset_pipeline_routes/routes"
|
3
4
|
|
4
5
|
module AssetPipelineRoutes
|
5
6
|
class Railtie < ::Rails::Railtie
|
6
7
|
initializer "asset_pipeline_routes.environment" do |app|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
ActiveSupport.on_load(:action_view) do
|
9
|
+
include ::AssetPipelineRoutes::RoutesContext
|
10
|
+
|
11
|
+
app.assets.context_class.instance_eval do
|
12
|
+
include ::AssetPipelineRoutes::RoutesContext
|
12
13
|
end
|
13
|
-
|
14
|
+
end
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module AssetPipelineRoutes
|
3
|
+
class Path
|
4
|
+
DEFAULT_REPLACEMENT = '{{\1}}'
|
5
|
+
|
6
|
+
attr_accessor :route
|
7
|
+
|
8
|
+
def self.proc_for_route route
|
9
|
+
proc { |id_replacement = DEFAULT_REPLACEMENT, *args|
|
10
|
+
proc { |route, replacement, *mapping|
|
11
|
+
Path.new(route.path.ast.to_s).build replacement, *mapping
|
12
|
+
}.curry[route].call(id_replacement, *args)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize route_str
|
17
|
+
@route = route_str
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply_format options = {}
|
21
|
+
@route = @route.sub(/\(\.:\w+\)/,format(options))
|
22
|
+
end
|
23
|
+
|
24
|
+
def build *args
|
25
|
+
apply_format args.extract_options!
|
26
|
+
replacements(*args).inject(@route) { |route, param|
|
27
|
+
route.sub(/:(\w+)/, param.to_s)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def format options
|
32
|
+
str = options.fetch(:format) { '' }
|
33
|
+
str = ".#{str}" unless str.empty? && str[0] != '.'
|
34
|
+
str
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_replacements
|
38
|
+
Array.new(number_of_replacements, DEFAULT_REPLACEMENT)
|
39
|
+
end
|
40
|
+
|
41
|
+
def replacements *args
|
42
|
+
defaults = default_replacements
|
43
|
+
defaults[0...args.length] = args
|
44
|
+
defaults
|
45
|
+
end
|
46
|
+
|
47
|
+
def number_of_replacements
|
48
|
+
@route.scan(/:(\w+)/).inject(0) { |sum, n| sum + 1 }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require "active_support/core_ext/array/extract_options"
|
3
|
+
|
4
|
+
require_relative "routes_context"
|
5
|
+
require_relative "js_function_helper"
|
6
|
+
require_relative "path"
|
7
|
+
|
8
|
+
module AssetPipelineRoutes
|
9
|
+
class Routes
|
10
|
+
def initialize routes
|
11
|
+
define_application_routes routes
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_application_routes routes
|
15
|
+
routes.select{ |route| named_route?(route) }.each do |route|
|
16
|
+
define_route route
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_route route
|
21
|
+
self.class.instance_eval do
|
22
|
+
define_method :"#{route.name}_path", Path.proc_for_route(route)
|
23
|
+
|
24
|
+
define_method :"#{route.name}_path_method" do |style = :js|
|
25
|
+
AssetPipelineRoutes::JsFunctionHelper::route_to_anonymous_function Path.new(route.path.ast.to_s).build(':\1'), style
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def named_route? route
|
31
|
+
!route.name.nil?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -4,60 +4,78 @@ def build_route name, path
|
|
4
4
|
OpenStruct.new({:name => name, :path => OpenStruct.new(:ast => path)})
|
5
5
|
end
|
6
6
|
|
7
|
-
describe AssetPipelineRoutes do
|
7
|
+
describe AssetPipelineRoutes::Routes do
|
8
8
|
# the @route property basically describes a RouteSet#routes object
|
9
9
|
# as Rails.application.routes.routes[:index] returns it
|
10
10
|
describe 'resources#index' do
|
11
11
|
before { @route = build_route 'users', '/users(.:format)' }
|
12
|
-
subject { AssetPipelineRoutes::
|
12
|
+
subject { AssetPipelineRoutes::Routes.new [@route] }
|
13
13
|
|
14
14
|
it { should respond_to(:users_path) }
|
15
15
|
its(:users_path) { should eql '/users'}
|
16
16
|
it { subject.users_path('\d+').should eql('/users') }
|
17
|
+
|
18
|
+
describe "with format" do
|
19
|
+
it { subject.users_path(format: 'json').should eql('/users.json') }
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
describe 'resources#show' do
|
20
24
|
before { @route = build_route 'user', '/users/:id(.:format)' }
|
21
|
-
subject { AssetPipelineRoutes::
|
25
|
+
subject { AssetPipelineRoutes::Routes.new [@route] }
|
22
26
|
|
23
27
|
it { should respond_to(:user_path) }
|
24
28
|
its(:user_path) { should eql('/users/{{id}}') }
|
25
29
|
it { subject.user_path('\d+').should eql('/users/\d+') }
|
30
|
+
|
31
|
+
describe "with format" do
|
32
|
+
it { subject.user_path('\d+', format: 'json').should eql('/users/\d+.json') }
|
33
|
+
it { subject.user_path(42, format: 'xml').should eql('/users/42.xml') }
|
34
|
+
end
|
26
35
|
end
|
27
36
|
|
28
37
|
describe 'resources#edit' do
|
29
38
|
before { @route = build_route 'edit_user', '/users/:id/edit(.:format)' }
|
30
|
-
subject { AssetPipelineRoutes::
|
39
|
+
subject { AssetPipelineRoutes::Routes.new [@route] }
|
31
40
|
|
32
41
|
it { should respond_to(:edit_user_path) }
|
33
42
|
its(:edit_user_path) { should eql('/users/{{id}}/edit') }
|
34
43
|
it { subject.edit_user_path('\d+').should eql('/users/\d+/edit') }
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'resources without name' do
|
38
|
-
before { @route = build_route nil, '/foo' }
|
39
|
-
subject { AssetPipelineRoutes::RoutesHelper.new [@route] }
|
40
44
|
|
41
|
-
|
45
|
+
describe "with format" do
|
46
|
+
it { subject.edit_user_path('\d+', format: 'json').should eql('/users/\d+/edit.json') }
|
47
|
+
it { subject.edit_user_path(42, format: 'xml').should eql('/users/42/edit.xml') }
|
48
|
+
end
|
42
49
|
end
|
43
50
|
|
44
51
|
describe 'nested routes' do
|
45
52
|
before { @route = build_route 'project_ticket', '/projects/:project_id/tickets/:id(.:format)' }
|
46
|
-
subject { AssetPipelineRoutes::
|
53
|
+
subject { AssetPipelineRoutes::Routes.new [@route] }
|
47
54
|
|
48
55
|
it { should respond_to(:project_ticket_path) }
|
49
|
-
its(:project_ticket_path) {
|
56
|
+
its(:project_ticket_path) {should eql('/projects/{{project_id}}/tickets/{{id}}') }
|
57
|
+
it { subject.project_ticket_path(1,'\d+').should eql('/projects/1/tickets/\d+') }
|
58
|
+
it { subject.project_ticket_path('\d+',2).should eql('/projects/\d+/tickets/2') }
|
59
|
+
it { subject.project_ticket_path(1,2).should eql('/projects/1/tickets/2') }
|
60
|
+
it { subject.project_ticket_path(1,2,3).should eql('/projects/1/tickets/2') }
|
61
|
+
|
62
|
+
describe "with format" do
|
63
|
+
it { subject.project_ticket_path("a","b",format: 'json').should eql('/projects/a/tickets/b.json') }
|
64
|
+
it { subject.project_ticket_path("a", format: 'json').should eql('/projects/a/tickets/{{id}}.json') }
|
65
|
+
end
|
50
66
|
end
|
51
67
|
|
52
68
|
describe 'javascript method generation' do
|
53
69
|
before { @route = build_route 'user', '/users/:id/edit(.:format)' }
|
54
|
-
subject { AssetPipelineRoutes::
|
70
|
+
subject { AssetPipelineRoutes::Routes.new [@route] }
|
55
71
|
|
56
72
|
it { should respond_to(:user_path_method) }
|
73
|
+
|
57
74
|
it "should generate JavaScript mapping method" do
|
58
75
|
js_method = "(function() { return function (id) { return '/users/' + id + '/edit' }; }).call(this);"
|
59
76
|
subject.edit_user_path_method.should eql(js_method)
|
60
77
|
end
|
78
|
+
|
61
79
|
it "should generate CoffeScript mapping method" do
|
62
80
|
coffee_method = "(-> (id) -> '/users/' + id + '/edit')(this)"
|
63
81
|
subject.edit_user_path_method(:coffee).should eql(coffee_method)
|
data/spec/path_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AssetPipelineRoutes::Path do
|
4
|
+
subject { AssetPipelineRoutes::Path.new '/users/:id/edit(.:format)' }
|
5
|
+
|
6
|
+
describe 'apply_format' do
|
7
|
+
it { subject.apply_format({ format: 'json' }).should eql '/users/:id/edit.json' }
|
8
|
+
it { subject.apply_format({}).should eql '/users/:id/edit' }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'format' do
|
12
|
+
it { subject.format({ format: 'json' }).should == '.json' }
|
13
|
+
it { subject.format({}).should == '' }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'after applying formats' do
|
17
|
+
before { subject.apply_format }
|
18
|
+
|
19
|
+
describe 'number_of_replacements' do
|
20
|
+
it { subject.number_of_replacements.should == 1 }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'default_replacements' do
|
24
|
+
it { subject.default_replacements.should eql [AssetPipelineRoutes::Path::DEFAULT_REPLACEMENT]}
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'replacements' do
|
28
|
+
it { subject.replacements().should eql subject.default_replacements }
|
29
|
+
it { subject.replacements(1).should eql [1] }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asset_pipeline_routes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &70101206508480 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70101206508480
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activesupport
|
27
|
-
requirement: &
|
27
|
+
requirement: &70101206507700 !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: *70101206507700
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70101206506900 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70101206506900
|
47
47
|
description: Add a routes helper for all asset pipeline needs
|
48
48
|
email:
|
49
49
|
- nicolai86@me.com
|
@@ -52,11 +52,13 @@ extensions: []
|
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
54
|
- lib/asset_pipeline_routes/js_function_helper.rb
|
55
|
+
- lib/asset_pipeline_routes/path.rb
|
56
|
+
- lib/asset_pipeline_routes/routes.rb
|
55
57
|
- lib/asset_pipeline_routes/routes_context.rb
|
56
|
-
- lib/asset_pipeline_routes/routes_helper.rb
|
57
58
|
- lib/asset_pipeline_routes/version.rb
|
58
59
|
- lib/asset_pipeline_routes.rb
|
59
60
|
- spec/asset_pipeline_routes_spec.rb
|
61
|
+
- spec/path_spec.rb
|
60
62
|
- spec/spec_helper.rb
|
61
63
|
- README.md
|
62
64
|
- Rakefile
|
@@ -80,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
82
|
version: '0'
|
81
83
|
requirements: []
|
82
84
|
rubyforge_project: asset_pipeline_routes
|
83
|
-
rubygems_version: 1.8.
|
85
|
+
rubygems_version: 1.8.17
|
84
86
|
signing_key:
|
85
87
|
specification_version: 3
|
86
88
|
summary: Add a routes helper for all asset pipeline needs
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative "routes_context"
|
2
|
-
require_relative "js_function_helper"
|
3
|
-
|
4
|
-
module AssetPipelineRoutes
|
5
|
-
class RoutesHelper
|
6
|
-
def initialize(routes, default_block = '{{\1}}')
|
7
|
-
routes.each do |route|
|
8
|
-
next if route.name.nil? # only handle named_routes
|
9
|
-
|
10
|
-
self.class.instance_eval do
|
11
|
-
define_method :"#{route.name}_path" do |id_replacement = default_block|
|
12
|
-
proc { |route, mapping| build_url route, mapping }.curry[route].call id_replacement
|
13
|
-
end
|
14
|
-
|
15
|
-
define_method :"#{route.name}_path_method" do |style = :js|
|
16
|
-
AssetPipelineRoutes::JsFunctionHelper::route_to_anonymous_function build_url(route, ':\1'), style
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def build_url route, mapping
|
23
|
-
route.path.ast.to_s.gsub(/\(\.:\w+\)/,'').gsub(/:(\w+)/, mapping).to_s
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|