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 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 all resource links dynamic params at compile-time to work, like `{:id => 42}`. Without supplying them you won't get anywhere.
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
- editUserRoute = `<%= r.edit_user_method %>` # => yields anonymous function
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/routes_helper"
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
- ActiveSupport.on_load(:action_view) do
8
- include ::AssetPipelineRoutes::RoutesContext
9
-
10
- app.assets.context_class.instance_eval do
11
- include ::AssetPipelineRoutes::RoutesContext
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
- end
14
+ end
14
15
  end
15
16
  end
16
17
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'active_support/core_ext/string/inflections'
2
3
 
3
4
  module AssetPipelineRoutes
@@ -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
@@ -1,9 +1,8 @@
1
+ # encoding: UTF-8
1
2
  module AssetPipelineRoutes
2
3
  module RoutesContext
3
-
4
4
  def r
5
- @r ||= ::AssetPipelineRoutes::RoutesHelper.new(Rails.application.routes.routes)
5
+ @r ||= ::AssetPipelineRoutes::Routes.new(Rails.application.routes.routes)
6
6
  end
7
-
8
7
  end
9
8
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module AssetPipelineRoutes
2
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
3
4
  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::RoutesHelper.new [@route] }
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::RoutesHelper.new [@route] }
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::RoutesHelper.new [@route] }
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
- it { subject.should_not_receive(:build_url) }
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::RoutesHelper.new [@route] }
53
+ subject { AssetPipelineRoutes::Routes.new [@route] }
47
54
 
48
55
  it { should respond_to(:project_ticket_path) }
49
- its(:project_ticket_path) { should eql('/projects/{{project_id}}/tickets/{{id}}') }
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::RoutesHelper.new [@route] }
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
@@ -2,6 +2,7 @@ ENV["RAILS_ENV"] = "test"
2
2
 
3
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
- require 'asset_pipeline_routes/routes_helper'
5
+ require 'asset_pipeline_routes/routes'
6
+ require 'asset_pipeline_routes/path'
6
7
  require 'rspec'
7
8
  require 'ostruct'
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.3
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-02-04 00:00:00.000000000 Z
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: &70170979291500 !ruby/object:Gem::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: *70170979291500
24
+ version_requirements: *70101206508480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &70170979291080 !ruby/object:Gem::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: *70170979291080
35
+ version_requirements: *70101206507700
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70170979290620 !ruby/object:Gem::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: *70170979290620
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.15
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