tred-fancyroutes 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 The TRED Team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,155 @@
1
+ FancyRoutes
2
+ ===========
3
+
4
+ Removing the cruft, bringing the HTTP method to the forefront and sporting a
5
+ neat DRYing block syntax--FancyRoutes is a layer on top of the Rails routing
6
+ system which provides an elegant API for mapping requests to your
7
+ application's controllers and actions.
8
+
9
+ Take for example the following routes from one of Myles' applications:
10
+
11
+ map.connect '/orders', :controller => 'orders', :action => 'index, :conditions => { :method => :get }
12
+
13
+ map.connect '/:slug/order', :controller => 'orders', :action => :show, :conditions => { :method => :get }
14
+ map.connect '/:slug/order', :controller => 'orders', :action => :create, :conditions => { :method => :post }
15
+
16
+ map.connect 'item_images/:image', :controller => 'item_images', :action => 'show', :conditions => { :method => :get }
17
+
18
+ Converted to fancyroutes these now look like:
19
+
20
+ get / 'orders' >> :orders > :index
21
+
22
+ with route / :slug / 'order' >> :orders do
23
+ get > :show
24
+ put > :update
25
+ end
26
+
27
+ get {'item_images' => :controller} / :image > :show
28
+
29
+ So fancy!
30
+
31
+ Where'd all the parentheses go?
32
+ -------------------------------
33
+
34
+ We use three of Ruby's operators to define paths:
35
+
36
+ * `/` separates the segments
37
+ * `>>` indicates the controller
38
+ * `>` indicates the action
39
+
40
+ Segments of the path can be strings or symbols. Symbols, such as `:image`, define parameters and strings, such as `'order'`, define static segments.
41
+
42
+ Controller names in the path
43
+ ----------------------------
44
+
45
+ Quite often the controller name will already be in the path itself.
46
+
47
+ map.connect '/playground/:action', :controller => 'playground'
48
+
49
+ Don't repeat yourself! Provide a hash instead:
50
+
51
+ get / {'playground' => :controller} / :action
52
+
53
+ Named routes
54
+ ------------
55
+
56
+ Simply suffix the get/post/put/delete with the name:
57
+
58
+ page.get / '*tree' >> :pages > :show
59
+
60
+ Now you can generate a path with the route:
61
+
62
+ page_path(["help", "where-is-the-any-key"])
63
+
64
+ Nesting routes
65
+ --------------
66
+
67
+ Use `with route` to DRY up similar routes. For example:
68
+
69
+ get / :slug / 'order' >> :orders > :show
70
+ put / :slug / 'order' >> :orders > :update
71
+
72
+ can be rewritten as:
73
+
74
+ with route / :slug >> :orders do
75
+ get / 'order' > :show
76
+ put / 'order' > :update
77
+ end
78
+
79
+ or even better:
80
+
81
+ with route / :slug / 'order' >> :orders do
82
+ get > :show
83
+ put > :update
84
+ end
85
+
86
+ The root route
87
+ --------------
88
+
89
+ A standard root route looks something like this:
90
+
91
+ map.root :controller => 'homepage', :action => 'index'
92
+
93
+ The fancier version is:
94
+
95
+ root >> :homepage > :index
96
+
97
+ Installing
98
+ ----------
99
+
100
+ Install the gem:
101
+
102
+ sudo gem install tred-fancyroutes
103
+
104
+ add the dependency in your environment.rb:
105
+
106
+ config.gem 'tred-fancyroutes'
107
+
108
+ and then use the FancyRoutes method in your routes.rb:
109
+
110
+ ActionController::Routing::Routes.draw do |map|
111
+ FancyRoutes(map) do
112
+ # the
113
+ # fanciest
114
+ # routes
115
+ # you
116
+ # ever
117
+ # did
118
+ # see
119
+ end
120
+ end
121
+
122
+ Contributors
123
+ ------------
124
+
125
+ * Myles Byrne
126
+ * Carl Woodward
127
+ * Tim Lucas
128
+ * Chris Lloyd
129
+ * Michael Koukoullis
130
+ * Lincoln Stolli
131
+ * Dave Newman
132
+
133
+ License (MIT)
134
+ -------------
135
+
136
+ Copyright (c) 2008-09 The TRED Team
137
+
138
+ Permission is hereby granted, free of charge, to any person obtaining
139
+ a copy of this software and associated documentation files (the
140
+ "Software"), to deal in the Software without restriction, including
141
+ without limitation the rights to use, copy, modify, merge, publish,
142
+ distribute, sublicense, and/or sell copies of the Software, and to
143
+ permit persons to whom the Software is furnished to do so, subject to
144
+ the following conditions:
145
+
146
+ The above copyright notice and this permission notice shall be
147
+ included in all copies or substantial portions of the Software.
148
+
149
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
150
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
151
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
152
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
153
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
154
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
155
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'spec/rake/spectask'
6
+
7
+ GEM = "fancyroutes"
8
+ GEM_VERSION = "0.9.1"
9
+ AUTHOR = "The TRED Team"
10
+ EMAIL = "tred3000@gmail.com"
11
+ HOMEPAGE = "http://tred.github.com/fancyroutes"
12
+ SUMMARY = "Removing the cruft, bringing the HTTP method to the forefront and sporting a neat DRYing block syntax--FancyRoutes is a layer on top of the Rails routing system which provides an elegant API for mapping requests to your application's controllers and actions."
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = GEM
16
+ s.version = GEM_VERSION
17
+ s.platform = Gem::Platform::RUBY
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = ['README.md', 'LICENSE']
20
+ s.description = s.summary
21
+ s.author = AUTHOR
22
+ s.email = EMAIL
23
+ s.homepage = HOMEPAGE
24
+ s.summary = SUMMARY
25
+
26
+ s.require_path = 'lib'
27
+ s.autorequire = GEM
28
+ s.files = %w(LICENSE README.md Rakefile) + Dir.glob("{lib,spec}/**/*")
29
+ end
30
+
31
+ task :default => :spec
32
+
33
+ desc "Run specs"
34
+ Spec::Rake::SpecTask.new do |t|
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ t.spec_opts = %w(-fs --color)
37
+ end
38
+
39
+
40
+ Rake::GemPackageTask.new(spec) do |pkg|
41
+ pkg.gem_spec = spec
42
+ end
43
+
44
+ desc "install the gem locally"
45
+ task :install => [:package] do
46
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
47
+ end
48
+
49
+ desc "create a gemspec file"
50
+ task :make_spec do
51
+ File.open("#{GEM}.gemspec", "w") do |file|
52
+ file.puts spec.to_ruby
53
+ end
54
+ end
@@ -0,0 +1,127 @@
1
+ module FancyRoutes
2
+
3
+ class Route
4
+
5
+ def initialize
6
+ @segments = []
7
+ end
8
+
9
+ def request_method(method)
10
+ @request_method = method.to_sym
11
+ self
12
+ end
13
+
14
+ %w(get put post delete).each do |meth|
15
+ define_method(meth) { request_method(meth) }
16
+ end
17
+
18
+ attr_writer :name
19
+
20
+ def segment(segment)
21
+ segment = case segment
22
+ when Symbol
23
+ ":#{segment}"
24
+ when Hash
25
+ self.send(segment.values.first, segment.keys.first)
26
+ segment.keys.first.to_s
27
+ else
28
+ segment.to_s
29
+ end
30
+ @segments << segment
31
+ self
32
+ end
33
+ alias_method :/, :segment
34
+
35
+ def controller(controller)
36
+ @controller = controller.to_s
37
+ self
38
+ end
39
+ alias_method :>>, :controller
40
+
41
+ def action(action)
42
+ @action = action.to_s
43
+ self
44
+ end
45
+ alias_method :>, :action
46
+
47
+ def apply(rails_map)
48
+ rails_map.send( (@name ? @name : :connect),
49
+ @segments.join("/"), {
50
+ :controller => @controller,
51
+ :action => @action,
52
+ :conditions => { :method => @request_method }
53
+ }
54
+ )
55
+ end
56
+
57
+ # hacky deep clone
58
+ def copy
59
+ Marshal::load(Marshal.dump(self))
60
+ end
61
+
62
+ end
63
+
64
+ class RootRoute < Route
65
+
66
+ def apply(rails_map)
67
+ rails_map.root :controller => @controller,
68
+ :action => @action,
69
+ :conditions => { :method => @request_method }
70
+ end
71
+
72
+ end
73
+
74
+ # may be clearer to use 3 classes here: RouteSet, MasterSet & NestedSet
75
+
76
+ class RouteSet
77
+
78
+ attr_reader :routes
79
+
80
+ def initialize(template_route = nil)
81
+ @template_route = template_route
82
+ @routes = []
83
+ end
84
+
85
+ def apply(rails_route_map)
86
+ @routes.each { |route| route.apply(rails_route_map) }
87
+ end
88
+
89
+ # builds a new route
90
+ def route(meth = nil, name = nil)
91
+ route = @template_route ? @template_route.copy : (name == :root ? RootRoute.new : Route.new)
92
+ route.request_method(meth) if meth
93
+ route.name = name if name
94
+ @routes << route
95
+ route
96
+ end
97
+
98
+ %w(get put post delete).each do |meth|
99
+ define_method(meth) { route(meth) }
100
+ end
101
+
102
+ def root
103
+ route(:get, :root)
104
+ end
105
+
106
+ def method_missing(meth,*args)
107
+ route(nil,meth)
108
+ end
109
+
110
+ def with(route, &blk)
111
+ # this route is used as a template, not as an actual route so we remove
112
+ # it from the routes collection
113
+ @routes.pop
114
+ nested_set = self.class.new(route)
115
+ nested_set.instance_eval(&blk)
116
+ @routes += nested_set.routes
117
+ end
118
+
119
+ end
120
+
121
+ end
122
+
123
+ def FancyRoutes(m, &blk)
124
+ fr = FancyRoutes::RouteSet.new
125
+ fr.instance_eval(&blk)
126
+ fr.apply(m)
127
+ end
@@ -0,0 +1,131 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "FancyRoutes" do
4
+
5
+ before(:each) do
6
+ @map = Object.new
7
+ end
8
+
9
+ # without helpers
10
+
11
+ example "route on root, long form" do
12
+ mock(@map).connect('', {
13
+ :controller => 'my_controller',
14
+ :action => 'my_action',
15
+ :conditions => { :method => :get },
16
+ })
17
+
18
+ FancyRoutes(@map) do
19
+ route(:get).segment('').controller(:my_controller).action(:my_action)
20
+ end
21
+ end
22
+
23
+ # an now lets dry up the mocking and route building
24
+
25
+ def fancyroutes(&blk)
26
+ FancyRoutes(@map,&blk)
27
+ end
28
+
29
+ def expect(meth, path, controller, action)
30
+ mock(@map).connect(path, {
31
+ :controller => controller,
32
+ :action => action,
33
+ :conditions => { :method => meth },
34
+ })
35
+ end
36
+
37
+ example "short form route on root" do
38
+ expect :get, '', 'my_controller', 'my_action'
39
+
40
+ fancyroutes do
41
+ get / '' >> :my_controller > :my_action
42
+ end
43
+ end
44
+
45
+ example "short form route on order" do
46
+ expect :get, ':slug/order', 'my_controller', 'my_action'
47
+
48
+ fancyroutes do
49
+ get / :slug / 'order' >> :my_controller > :my_action
50
+ end
51
+ end
52
+
53
+ example "short form route on order as put" do
54
+ expect :put, ':slug/order', 'my_controller', 'my_action'
55
+
56
+ fancyroutes do
57
+ put / :slug / 'order' >> :my_controller > :my_action
58
+ end
59
+ end
60
+
61
+ example "short form route nested route" do
62
+ expect :get, ':slug/order', 'my_controller', 'get_action'
63
+ expect :post, ':slug/order', 'my_controller', 'post_action'
64
+
65
+ fancyroutes do
66
+ with route / :slug >> :my_controller do
67
+ get / 'order' > :get_action
68
+ post / 'order' > :post_action
69
+ end
70
+ end
71
+ end
72
+
73
+ example "short form route nested route on method only" do
74
+ expect :get, ':slug/order', 'my_controller', 'get_action'
75
+ expect :post, ':slug/order', 'my_controller', 'post_action'
76
+
77
+ fancyroutes do
78
+ with route / :slug / 'order' >> :my_controller do
79
+ get > :get_action
80
+ post > :post_action
81
+ end
82
+ end
83
+ end
84
+
85
+ example "nested in nested routes" do
86
+ expect :get, ':slug/order', 'my_controller', 'get_action'
87
+ expect :post, ':slug/order', 'my_controller', 'post_action'
88
+
89
+ fancyroutes do
90
+ with route / :slug do
91
+ with route >> :my_controller do
92
+ get / 'order' > :get_action
93
+ post / 'order' > :post_action
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ example "with named segment" do
100
+ expect :get, 'my_controller/:image', 'my_controller', 'my_action'
101
+
102
+ fancyroutes do
103
+ get / {'my_controller' => :controller} / :image > :my_action
104
+ end
105
+ end
106
+
107
+ example "a named route" do
108
+ mock(@map).my_name('my_controller/:image', {
109
+ :controller => 'my_controller',
110
+ :action => 'my_action',
111
+ :conditions => { :method => :get }
112
+ })
113
+
114
+ fancyroutes do
115
+ my_name.get / {'my_controller' => :controller} / :image > :my_action
116
+ end
117
+ end
118
+
119
+ example "root route" do
120
+ mock(@map).root(
121
+ :controller => 'my_controller',
122
+ :action => 'my_action',
123
+ :conditions => { :method => :get }
124
+ )
125
+
126
+ fancyroutes do
127
+ root >> :my_controller > :my_action
128
+ end
129
+ end
130
+
131
+ end
@@ -0,0 +1,7 @@
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'rubygems'
3
+ require 'fancyroutes'
4
+
5
+ Spec::Runner.configure do |config|
6
+ config.mock_with :rr
7
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tred-fancyroutes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - The TRED Team
8
+ autorequire: fancyroutes
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-09 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: tred3000@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.md
24
+ - LICENSE
25
+ files:
26
+ - LICENSE
27
+ - README.md
28
+ - Rakefile
29
+ - lib/fancyroutes.rb
30
+ - spec/fancyroutes_spec.rb
31
+ - spec/spec_helper.rb
32
+ has_rdoc: true
33
+ homepage: http://tred.github.com/fancyroutes
34
+ post_install_message:
35
+ rdoc_options: []
36
+
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project:
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: Removing the cruft, bringing the HTTP method to the forefront and sporting a neat DRYing block syntax--FancyRoutes is a layer on top of the Rails routing system which provides an elegant API for mapping requests to your application's controllers and actions.
58
+ test_files: []
59
+