josevalim-inherited_resources 0.7.3 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/README +8 -1
- data/lib/inherited_resources.rb +23 -0
- data/lib/inherited_resources/actions.rb +96 -0
- data/lib/inherited_resources/base.rb +6 -110
- data/lib/inherited_resources/base_helpers.rb +12 -16
- data/lib/inherited_resources/class_methods.rb +20 -25
- data/lib/inherited_resources/singleton_helpers.rb +2 -2
- data/lib/inherited_resources/url_helpers.rb +79 -122
- data/test/aliases_test.rb +2 -1
- data/test/base_test.rb +4 -1
- data/test/class_methods_test.rb +3 -3
- data/test/redirect_to_test.rb +22 -53
- metadata +3 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# Version 0.8
|
2
|
+
|
3
|
+
* Allow InheritedResources to be called without inheritance.
|
4
|
+
* Ensure that controllers that inherit from a controller with InheritedResources
|
5
|
+
works properly.
|
6
|
+
|
1
7
|
# Version 0.7
|
2
8
|
|
3
9
|
* Allow procs as default value in has scope to be able to use values from session, for example.
|
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Inherited Resources
|
2
2
|
License: MIT
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.0
|
4
4
|
|
5
5
|
You can also read this README in pretty html at the GitHub project Wiki page:
|
6
6
|
|
@@ -93,6 +93,13 @@ In your views, you will get the following helpers:
|
|
93
93
|
As you might expect, collection (@projects instance variable) is only available
|
94
94
|
on index actions.
|
95
95
|
|
96
|
+
If for some reason you cannot inherit from InheritedResources::Base, you can
|
97
|
+
call inherit_resources or resource_controller in your controller class scope:
|
98
|
+
|
99
|
+
class AccountsController < ApplicationController
|
100
|
+
inherit_resources # or resource_controller
|
101
|
+
end
|
102
|
+
|
96
103
|
Overwriting defaults
|
97
104
|
--------------------
|
98
105
|
|
data/lib/inherited_resources.rb
CHANGED
@@ -4,3 +4,26 @@
|
|
4
4
|
require File.join(File.dirname(__FILE__), 'inherited_resources', 'respond_to')
|
5
5
|
|
6
6
|
module InheritedResources; end
|
7
|
+
|
8
|
+
class ActionController::Base
|
9
|
+
class << self
|
10
|
+
# If you cannot inherit from InheritedResources::Base you can call
|
11
|
+
# inherit_resource or resource_controller in your controller to have all
|
12
|
+
# the required modules and funcionality included.
|
13
|
+
#
|
14
|
+
def inherit_resources
|
15
|
+
include InheritedResources::Actions
|
16
|
+
include InheritedResources::BaseHelpers
|
17
|
+
extend InheritedResources::ClassMethods
|
18
|
+
extend InheritedResources::UrlHelpers
|
19
|
+
|
20
|
+
helper_method :collection_url, :collection_path, :resource_url, :resource_path,
|
21
|
+
:new_resource_url, :new_resource_path, :edit_resource_url, :edit_resource_path,
|
22
|
+
:resource, :collection, :resource_class
|
23
|
+
|
24
|
+
initialize_resources_class_accessors!
|
25
|
+
create_resources_url_helpers!
|
26
|
+
end
|
27
|
+
alias :resource_controller :inherit_resources
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module InheritedResources
|
2
|
+
RESOURCES_ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:RESOURCES_ACTIONS)
|
3
|
+
|
4
|
+
# Holds all default actions for InheritedResouces.
|
5
|
+
module Actions
|
6
|
+
|
7
|
+
# GET /resources
|
8
|
+
def index(&block)
|
9
|
+
respond_to(:with => collection, &block)
|
10
|
+
end
|
11
|
+
alias :index! :index
|
12
|
+
|
13
|
+
# GET /resources/1
|
14
|
+
def show(&block)
|
15
|
+
respond_to(:with => resource, &block)
|
16
|
+
end
|
17
|
+
alias :show! :show
|
18
|
+
|
19
|
+
# GET /resources/new
|
20
|
+
def new(&block)
|
21
|
+
respond_to(:with => build_resource, &block)
|
22
|
+
end
|
23
|
+
alias :new! :new
|
24
|
+
|
25
|
+
# GET /resources/1/edit
|
26
|
+
def edit(&block)
|
27
|
+
respond_to(:with => resource, &block)
|
28
|
+
end
|
29
|
+
alias :edit! :edit
|
30
|
+
|
31
|
+
# POST /resources
|
32
|
+
def create(redirect_url=nil, &block)
|
33
|
+
object = build_resource(params[resource_instance_name])
|
34
|
+
respond_block, redirect_block = select_block_by_arity(block)
|
35
|
+
|
36
|
+
if object.save
|
37
|
+
set_flash_message!(:notice, '{{resource_name}} was successfully created.')
|
38
|
+
options = { :with => object, :status => :created, :location => (resource_url rescue nil) }
|
39
|
+
|
40
|
+
respond_to_with_dual_blocks(true, respond_block, options) do |format|
|
41
|
+
format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) }
|
42
|
+
end
|
43
|
+
else
|
44
|
+
set_flash_message!(:error)
|
45
|
+
options = { :with => object.errors, :status => :unprocessable_entity }
|
46
|
+
|
47
|
+
respond_to_with_dual_blocks(false, respond_block, options) do |format|
|
48
|
+
format.html { render :action => 'new' }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
alias :create! :create
|
53
|
+
|
54
|
+
# PUT /resources/1
|
55
|
+
def update(redirect_url=nil, &block)
|
56
|
+
object = resource
|
57
|
+
respond_block, redirect_block = select_block_by_arity(block)
|
58
|
+
|
59
|
+
if object.update_attributes(params[resource_instance_name])
|
60
|
+
set_flash_message!(:notice, '{{resource_name}} was successfully updated.')
|
61
|
+
|
62
|
+
respond_to_with_dual_blocks(true, block) do |format|
|
63
|
+
format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) }
|
64
|
+
format.all { head :ok }
|
65
|
+
end
|
66
|
+
else
|
67
|
+
set_flash_message!(:error)
|
68
|
+
|
69
|
+
options = { :with => object.errors, :status => :unprocessable_entity }
|
70
|
+
|
71
|
+
respond_to_with_dual_blocks(false, block, options) do |format|
|
72
|
+
format.html { render :action => 'edit' }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
alias :update! :update
|
77
|
+
|
78
|
+
# DELETE /resources/1
|
79
|
+
def destroy(redirect_url=nil, &block)
|
80
|
+
resource.destroy
|
81
|
+
respond_block, redirect_block = select_block_by_arity(block)
|
82
|
+
|
83
|
+
set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.')
|
84
|
+
|
85
|
+
respond_to_with_dual_blocks(nil, respond_block) do |format|
|
86
|
+
format.html { redirect_to(redirect_block ? redirect_block.call : collection_url) }
|
87
|
+
format.all { head :ok }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
alias :destroy! :destroy
|
91
|
+
|
92
|
+
# Make aliases protected
|
93
|
+
protected :index!, :show!, :new!, :create!, :edit!, :update!, :destroy!
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -1,13 +1,4 @@
|
|
1
|
-
# Whenever Base is required, we eager load the base files. belongs_to, polymorphic
|
2
|
-
# and singleton helpers are loaded on demand.
|
3
|
-
require File.dirname(__FILE__) + '/base_helpers.rb'
|
4
|
-
require File.dirname(__FILE__) + '/class_methods.rb'
|
5
|
-
require File.dirname(__FILE__) + '/dumb_responder.rb'
|
6
|
-
require File.dirname(__FILE__) + '/url_helpers.rb'
|
7
|
-
|
8
1
|
module InheritedResources
|
9
|
-
RESOURCES_ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:RESOURCES_ACTIONS)
|
10
|
-
|
11
2
|
# = Base
|
12
3
|
#
|
13
4
|
# This is the base class that holds all actions. If you see the code for each
|
@@ -20,114 +11,19 @@ module InheritedResources
|
|
20
11
|
class Base < ::ApplicationController
|
21
12
|
unloadable
|
22
13
|
|
14
|
+
include InheritedResources::Actions
|
23
15
|
include InheritedResources::BaseHelpers
|
24
|
-
extend
|
16
|
+
extend InheritedResources::ClassMethods
|
17
|
+
extend InheritedResources::UrlHelpers
|
25
18
|
|
26
19
|
helper_method :collection_url, :collection_path, :resource_url, :resource_path,
|
27
20
|
:new_resource_url, :new_resource_path, :edit_resource_url, :edit_resource_path,
|
28
21
|
:resource, :collection, :resource_class
|
29
22
|
|
30
23
|
def self.inherited(base) #:nodoc:
|
31
|
-
base
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
# Call super to register class in ApplicationController
|
37
|
-
super
|
38
|
-
|
39
|
-
# Creates and sets class accessors default values
|
40
|
-
initialize_resources_class_accessors!(base)
|
24
|
+
super(base)
|
25
|
+
base.send :initialize_resources_class_accessors!
|
26
|
+
base.send :create_resources_url_helpers!
|
41
27
|
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
# GET /resources
|
46
|
-
def index(&block)
|
47
|
-
respond_to(:with => collection, &block)
|
48
|
-
end
|
49
|
-
alias :index! :index
|
50
|
-
|
51
|
-
# GET /resources/1
|
52
|
-
def show(&block)
|
53
|
-
respond_to(:with => resource, &block)
|
54
|
-
end
|
55
|
-
alias :show! :show
|
56
|
-
|
57
|
-
# GET /resources/new
|
58
|
-
def new(&block)
|
59
|
-
respond_to(:with => build_resource, &block)
|
60
|
-
end
|
61
|
-
alias :new! :new
|
62
|
-
|
63
|
-
# GET /resources/1/edit
|
64
|
-
def edit(&block)
|
65
|
-
respond_to(:with => resource, &block)
|
66
|
-
end
|
67
|
-
alias :edit! :edit
|
68
|
-
|
69
|
-
# POST /resources
|
70
|
-
def create(redirect_url=nil, &block)
|
71
|
-
object = build_resource(params[resource_instance_name])
|
72
|
-
respond_block, redirect_block = select_block_by_arity(block)
|
73
|
-
|
74
|
-
if object.save
|
75
|
-
set_flash_message!(:notice, '{{resource_name}} was successfully created.')
|
76
|
-
options = { :with => object, :status => :created, :location => (resource_url rescue nil) }
|
77
|
-
|
78
|
-
respond_to_with_dual_blocks(true, respond_block, options) do |format|
|
79
|
-
format.html { redirect_to parse_redirect_url(redirect_url, :resource_url, redirect_block) }
|
80
|
-
end
|
81
|
-
else
|
82
|
-
set_flash_message!(:error)
|
83
|
-
|
84
|
-
options = { :with => object.errors, :status => :unprocessable_entity }
|
85
|
-
|
86
|
-
respond_to_with_dual_blocks(false, respond_block, options) do |format|
|
87
|
-
format.html { render :action => 'new' }
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
alias :create! :create
|
92
|
-
|
93
|
-
# PUT /resources/1
|
94
|
-
def update(redirect_url=nil, &block)
|
95
|
-
object = resource
|
96
|
-
respond_block, redirect_block = select_block_by_arity(block)
|
97
|
-
|
98
|
-
if object.update_attributes(params[resource_instance_name])
|
99
|
-
set_flash_message!(:notice, '{{resource_name}} was successfully updated.')
|
100
|
-
|
101
|
-
respond_to_with_dual_blocks(true, block) do |format|
|
102
|
-
format.html { redirect_to parse_redirect_url(redirect_url, :resource_url, redirect_block) }
|
103
|
-
format.all { head :ok }
|
104
|
-
end
|
105
|
-
else
|
106
|
-
set_flash_message!(:error)
|
107
|
-
|
108
|
-
options = { :with => object.errors, :status => :unprocessable_entity }
|
109
|
-
|
110
|
-
respond_to_with_dual_blocks(false, block, options) do |format|
|
111
|
-
format.html { render :action => 'edit' }
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
alias :update! :update
|
116
|
-
|
117
|
-
# DELETE /resources/1
|
118
|
-
def destroy(redirect_url=nil, &block)
|
119
|
-
resource.destroy
|
120
|
-
respond_block, redirect_block = select_block_by_arity(block)
|
121
|
-
|
122
|
-
set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.')
|
123
|
-
|
124
|
-
respond_to_with_dual_blocks(nil, respond_block) do |format|
|
125
|
-
format.html { redirect_to parse_redirect_url(redirect_url, :collection_url, redirect_block) }
|
126
|
-
format.all { head :ok }
|
127
|
-
end
|
128
|
-
end
|
129
|
-
alias :destroy! :destroy
|
130
|
-
|
131
28
|
end
|
132
29
|
end
|
133
|
-
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Whenever base is required load the dumb responder since it's used inside actions.
|
2
|
+
require File.dirname(__FILE__) + '/dumb_responder.rb'
|
3
|
+
|
1
4
|
module InheritedResources
|
2
5
|
# Base helpers for InheritedResource work. Some methods here can be overwriten
|
3
6
|
# and you will need to do that to customize your controllers from time to time.
|
@@ -42,7 +45,7 @@ module InheritedResources
|
|
42
45
|
# methods. You probably won't need to change it. Again, if you overwrite
|
43
46
|
# don't forget to cache the result in an instance_variable.
|
44
47
|
#
|
45
|
-
def build_resource(attributes
|
48
|
+
def build_resource(attributes={})
|
46
49
|
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, attributes))
|
47
50
|
end
|
48
51
|
|
@@ -126,7 +129,14 @@ module InheritedResources
|
|
126
129
|
# Returns the appropriated method to build the resource.
|
127
130
|
#
|
128
131
|
def method_for_build #:nodoc:
|
129
|
-
(begin_of_association_chain || parent?) ?
|
132
|
+
(begin_of_association_chain || parent?) ? method_for_association_build : :new
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the name of the method used for build the resource in cases
|
136
|
+
# where we have a parent. This is overwritten in singleton scenarios.
|
137
|
+
#
|
138
|
+
def method_for_association_build
|
139
|
+
:build
|
130
140
|
end
|
131
141
|
|
132
142
|
# Returns the name of the method to be called, before returning the end
|
@@ -297,20 +307,6 @@ module InheritedResources
|
|
297
307
|
[]
|
298
308
|
end
|
299
309
|
|
300
|
-
# If block is not nil, call it and uses the result as redirect to url.
|
301
|
-
# Otherwise, send the default url as message.
|
302
|
-
#
|
303
|
-
def parse_redirect_url(redirect_url, default_url, block) #:nodoc:
|
304
|
-
if redirect_url
|
305
|
-
line = caller.detect{|l| l =~ Regexp.new(Regexp.escape(RAILS_ROOT)) }
|
306
|
-
ActiveSupport::Deprecation.warn("#{action_name}!(redirect_url) is deprecated. " <<
|
307
|
-
"Use #{action_name}!{ redirect_url } instead.", [line])
|
308
|
-
return redirect_url
|
309
|
-
end
|
310
|
-
|
311
|
-
block ? block.call : send(default_url)
|
312
|
-
end
|
313
|
-
|
314
310
|
# Holds InheritedResources block structure. It returns two blocks: the first
|
315
311
|
# is used in respond_to blocks and the second is the redirect_to url.
|
316
312
|
#
|
@@ -53,7 +53,7 @@ module InheritedResources
|
|
53
53
|
config[key] = value.to_sym
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
create_resources_url_helpers!
|
57
57
|
end
|
58
58
|
|
59
59
|
# Defines wich actions to keep from the inherited controller.
|
@@ -244,7 +244,7 @@ module InheritedResources
|
|
244
244
|
if block_given?
|
245
245
|
class_eval(&block)
|
246
246
|
else
|
247
|
-
|
247
|
+
create_resources_url_helpers!
|
248
248
|
end
|
249
249
|
end
|
250
250
|
alias :nested_belongs_to :belongs_to
|
@@ -292,49 +292,44 @@ module InheritedResources
|
|
292
292
|
|
293
293
|
# Initialize resources class accessors and set their default values.
|
294
294
|
#
|
295
|
-
def initialize_resources_class_accessors!
|
295
|
+
def initialize_resources_class_accessors! #:nodoc:
|
296
296
|
# Add and protect class accessors
|
297
|
-
|
298
|
-
metaklass = (class << self; self; end)
|
297
|
+
metaklass = (class << self; self; end)
|
299
298
|
|
300
|
-
|
301
|
-
|
299
|
+
RESOURCES_CLASS_ACCESSORS.each do |cattr|
|
300
|
+
cattr_accessor "#{cattr}", :instance_writer => false
|
302
301
|
|
303
|
-
|
304
|
-
|
302
|
+
# Protect instance methods
|
303
|
+
self.send :protected, cattr
|
305
304
|
|
306
|
-
|
307
|
-
|
308
|
-
end
|
305
|
+
# Protect class writer
|
306
|
+
metaklass.send :protected, "#{cattr}="
|
309
307
|
end
|
310
308
|
|
311
309
|
# Initialize resource class
|
312
|
-
|
313
|
-
|
310
|
+
self.resource_class = begin
|
311
|
+
self.controller_name.classify.constantize
|
314
312
|
rescue NameError
|
315
313
|
nil
|
316
314
|
end
|
317
315
|
|
318
316
|
# Initialize resources configuration hash
|
319
|
-
|
320
|
-
config =
|
321
|
-
config[:collection_name] =
|
322
|
-
config[:instance_name] =
|
317
|
+
self.resources_configuration = {}
|
318
|
+
config = self.resources_configuration[:self] = {}
|
319
|
+
config[:collection_name] = self.controller_name.to_sym
|
320
|
+
config[:instance_name] = self.controller_name.singularize.to_sym
|
323
321
|
|
324
322
|
config[:route_collection_name] = config[:collection_name]
|
325
323
|
config[:route_instance_name] = config[:instance_name]
|
326
324
|
|
327
325
|
# Deal with namespaced controllers
|
328
|
-
namespaces =
|
326
|
+
namespaces = self.controller_path.split('/')[0..-2]
|
329
327
|
config[:route_prefix] = namespaces.join('_') unless namespaces.empty?
|
330
328
|
|
331
329
|
# Initialize polymorphic, singleton, scopes and belongs_to parameters
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
# Create helpers
|
337
|
-
InheritedResources::UrlHelpers.create_resources_url_helpers!(base)
|
330
|
+
self.parents_symbols = []
|
331
|
+
self.scopes_configuration = {}
|
332
|
+
self.resources_configuration[:polymorphic] = { :symbols => [], :optional => false }
|
338
333
|
end
|
339
334
|
|
340
335
|
end
|
@@ -80,8 +80,8 @@ module InheritedResources
|
|
80
80
|
|
81
81
|
# Returns the appropriated method to build the resource.
|
82
82
|
#
|
83
|
-
def
|
84
|
-
"build_#{resource_instance_name}"
|
83
|
+
def method_for_association_build #:nodoc:
|
84
|
+
:"build_#{resource_instance_name}"
|
85
85
|
end
|
86
86
|
|
87
87
|
# Sets the method_for_association_chain to nil. See <tt>resource</tt>
|
@@ -39,10 +39,9 @@ module InheritedResources
|
|
39
39
|
# When we are using polymorphic associations, those helpers rely on
|
40
40
|
# polymorphic_url Rails helper.
|
41
41
|
#
|
42
|
-
def
|
42
|
+
def create_resources_url_helpers!
|
43
43
|
resource_segments, resource_ivars = [], []
|
44
|
-
resource_config =
|
45
|
-
polymorphic = false
|
44
|
+
resource_config = self.resources_configuration[:self]
|
46
45
|
|
47
46
|
# Add route_prefix if any.
|
48
47
|
resource_segments << resource_config[:route_prefix] unless resource_config[:route_prefix].blank?
|
@@ -51,150 +50,108 @@ module InheritedResources
|
|
51
50
|
# Remember that we don't have to build the segments in polymorphic cases,
|
52
51
|
# because the url will be polymorphic_url.
|
53
52
|
#
|
54
|
-
|
53
|
+
self.parents_symbols.each do |symbol|
|
55
54
|
if symbol == :polymorphic
|
56
|
-
polymorphic = true
|
57
55
|
resource_ivars << :parent
|
58
56
|
else
|
59
|
-
config =
|
57
|
+
config = self.resources_configuration[symbol]
|
60
58
|
resource_segments << config[:route_name]
|
61
|
-
resource_ivars << config[:instance_name]
|
59
|
+
resource_ivars << :"@#{config[:instance_name]}"
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
|
-
|
63
|
+
singleton = self.resources_configuration[:self][:singleton]
|
64
|
+
polymorphic = self.parents_symbols.include?(:polymorphic)
|
65
|
+
|
66
|
+
collection_ivars = resource_ivars.dup
|
67
|
+
collection_segments = resource_segments.dup
|
68
|
+
|
69
|
+
# This is the default route configuration, later we have to deal with
|
70
|
+
# exception from polymorphic and singleton cases.
|
66
71
|
#
|
67
|
-
|
68
|
-
|
72
|
+
collection_segments << resource_config[:route_collection_name]
|
73
|
+
resource_segments << resource_config[:route_instance_name]
|
74
|
+
resource_ivars << :"@#{resource_config[:instance_name]}"
|
75
|
+
|
76
|
+
# In singleton cases, we do not send the current element instance variable
|
77
|
+
# because the id is not in the URL. For example, we should call:
|
69
78
|
#
|
70
|
-
#
|
79
|
+
# project_manager_url(@project)
|
71
80
|
#
|
72
|
-
#
|
73
|
-
# The collection_url for singleton is the parent show url. For example,
|
74
|
-
# if we have ProjectsController with ManagerController, where the second
|
75
|
-
# is the singleton, the collection url would be: project_url(@project).
|
81
|
+
# Instead of:
|
76
82
|
#
|
77
|
-
#
|
83
|
+
# project_manager_url(@project, @manager)
|
78
84
|
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
resource_segments.pop
|
83
|
-
else
|
84
|
-
generate_url_and_path_helpers(base, nil, :collection, resource_segments, resource_ivars, polymorphic)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Prepare and add new_resource_url
|
88
|
-
resource_segments << resource_config[:route_instance_name]
|
89
|
-
generate_url_and_path_helpers(base, :new, :resource, resource_segments, resource_ivars, polymorphic)
|
90
|
-
|
91
|
-
# We don't add the resource_ivar to edit and show url if singleton.
|
92
|
-
# Singletons are simply:
|
85
|
+
# Another exception in singleton cases is that collection url does not
|
86
|
+
# exist. In such cases, we create the parent collection url. So in the
|
87
|
+
# manager case above, the collection url will be:
|
93
88
|
#
|
94
|
-
#
|
89
|
+
# project_url(@project)
|
95
90
|
#
|
96
|
-
#
|
91
|
+
# If the singleton does not have a parent, it will default to root_url.
|
97
92
|
#
|
98
|
-
#
|
93
|
+
# Finally, polymorphic cases we have to give hints to the polymorphic url
|
94
|
+
# builder. This works by attaching new ivars as symbols or records.
|
99
95
|
#
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
generate_url_and_path_helpers(base, nil, :resource, resource_segments, resource_ivars, polymorphic)
|
104
|
-
generate_url_and_path_helpers(base, :edit, :resource, resource_segments, resource_ivars, polymorphic)
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.generate_url_and_path_helpers(base, prefix, name, resource_segments, resource_ivars, polymorphic=false) #:nodoc:
|
108
|
-
ivars = resource_ivars.map{|i| i == :parent ? :parent : "@#{i}" }
|
96
|
+
if singleton
|
97
|
+
collection_segments.pop
|
98
|
+
resource_ivars.pop
|
109
99
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
unless base.resources_configuration[:self][:singleton] || ivars.empty? ||
|
114
|
-
name == :collection || prefix == :new
|
115
|
-
ivars.push "(given_args.first || #{ivars.pop})"
|
100
|
+
if polymorphic
|
101
|
+
resource_ivars << resource_config[:instance_name].inspect
|
102
|
+
new_ivars = resource_ivars
|
116
103
|
end
|
104
|
+
elsif polymorphic
|
105
|
+
collection_ivars << 'resource_class.new'
|
106
|
+
end
|
117
107
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# Customization to allow polymorphic with singletons.
|
125
|
-
#
|
126
|
-
# Let's take the projects and companies where each one has one manager
|
127
|
-
# example. The url helpers would be:
|
128
|
-
#
|
129
|
-
# company_manager_url(@company)
|
130
|
-
# project_manager_url(@project)
|
131
|
-
#
|
132
|
-
# Notice how the manager is not sent in the helper, because it's a
|
133
|
-
# singleton. So, polymorphic urls would be:
|
134
|
-
#
|
135
|
-
# polymorphic_url(@company)
|
136
|
-
# polymorphic_url(@project)
|
137
|
-
#
|
138
|
-
# Obviously, this won't work properly. So in such polymorphic with
|
139
|
-
# singletons cases we have to do this:
|
140
|
-
#
|
141
|
-
# polymorphic_url(@company, 'manager')
|
142
|
-
# polymorphic_url(@project, 'manager')
|
143
|
-
#
|
144
|
-
# This is exactly what we are doing here.
|
145
|
-
#
|
146
|
-
# The other case to handle is collection and new helpers with
|
147
|
-
# polymorphic urls. In such cases, we usually would not send anything:
|
148
|
-
#
|
149
|
-
# project_tasks_url(@project)
|
150
|
-
# new_project_task_url(@project)
|
151
|
-
#
|
152
|
-
# But this wouldn't work with polymorphic urls by the same reason as
|
153
|
-
# singletons:
|
154
|
-
#
|
155
|
-
# polymorphic_url(@project)
|
156
|
-
# new_polymorphic_url(@project)
|
157
|
-
#
|
158
|
-
# So we have to do this:
|
159
|
-
#
|
160
|
-
# polymorphic_url(@project, Task.new)
|
161
|
-
# new_polymorphic_url(@project, Task.new)
|
162
|
-
#
|
163
|
-
if base.resources_configuration[:self][:singleton]
|
164
|
-
ivars << base.resources_configuration[:self][:instance_name].inspect unless name == :collection
|
165
|
-
elsif name == :collection || prefix == :new
|
166
|
-
ivars << 'resource_class.new'
|
167
|
-
end
|
108
|
+
generate_url_and_path_helpers nil, :collection, collection_segments, collection_ivars
|
109
|
+
generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars
|
110
|
+
generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars
|
111
|
+
generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars
|
112
|
+
end
|
168
113
|
|
169
|
-
|
114
|
+
def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc:
|
115
|
+
ivars = resource_ivars.dup
|
170
116
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
117
|
+
singleton = self.resources_configuration[:self][:singleton]
|
118
|
+
polymorphic = self.parents_symbols.include?(:polymorphic)
|
119
|
+
|
120
|
+
# If it's not a singleton, ivars are not empty, not a collection or
|
121
|
+
# not a "new" named route, we can pass a resource as argument.
|
122
|
+
#
|
123
|
+
unless singleton || ivars.empty? || name == :collection || prefix == :new
|
124
|
+
ivars.push "(given_args.first || #{ivars.pop})"
|
125
|
+
end
|
180
126
|
|
181
|
-
|
127
|
+
# When polymorphic is true, the segments must be replace by :polymorphic
|
128
|
+
# and ivars should be gathered into an array, which is compacted when
|
129
|
+
# optional.
|
130
|
+
#
|
131
|
+
if polymorphic
|
132
|
+
segments = :polymorphic
|
133
|
+
ivars = "[#{ivars.join(', ')}]"
|
134
|
+
ivars << '.compact' if self.resources_configuration[:polymorphic][:optional]
|
135
|
+
else
|
136
|
+
segments = resource_segments.empty? ? 'root' : resource_segments.join('_')
|
137
|
+
ivars = ivars.join(', ')
|
138
|
+
end
|
182
139
|
|
183
|
-
|
184
|
-
|
140
|
+
prefix = prefix ? "#{prefix}_" : ''
|
141
|
+
ivars << (ivars.empty? ? 'given_options' : ', given_options')
|
185
142
|
|
186
|
-
|
187
|
-
protected
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
143
|
+
class_eval <<-URL_HELPERS, __FILE__, __LINE__
|
144
|
+
protected
|
145
|
+
def #{prefix}#{name}_path(*given_args)
|
146
|
+
given_options = given_args.extract_options!
|
147
|
+
#{prefix}#{segments}_path(#{ivars})
|
148
|
+
end
|
192
149
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
URL_HELPERS
|
150
|
+
def #{prefix}#{name}_url(*given_args)
|
151
|
+
given_options = given_args.extract_options!
|
152
|
+
#{prefix}#{segments}_url(#{ivars})
|
153
|
+
end
|
154
|
+
URL_HELPERS
|
198
155
|
end
|
199
156
|
|
200
157
|
end
|
data/test/aliases_test.rb
CHANGED
data/test/base_test.rb
CHANGED
data/test/class_methods_test.rb
CHANGED
@@ -81,7 +81,7 @@ class DefaultsClassMethodTest < ActiveSupport::TestCase
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def test_url_helpers_are_recreated_when_defaults_change
|
84
|
-
|
84
|
+
BooksController.expects(:create_resources_url_helpers!).returns(true).once
|
85
85
|
BooksController.send(:defaults, :instance_name => 'string', :collection_name => 'strings')
|
86
86
|
end
|
87
87
|
end
|
@@ -104,7 +104,7 @@ class BelongsToErrorsTest < ActiveSupport::TestCase
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_block
|
107
|
-
|
107
|
+
DeansController.expects(:create_resources_url_helpers!).returns(true).once
|
108
108
|
DeansController.send(:belongs_to, :school) do
|
109
109
|
belongs_to :association
|
110
110
|
end
|
@@ -113,7 +113,7 @@ class BelongsToErrorsTest < ActiveSupport::TestCase
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_multiple_blocks
|
116
|
-
|
116
|
+
DeansController.expects(:create_resources_url_helpers!).returns(true).once
|
117
117
|
DeansController.send(:belongs_to, :school) do
|
118
118
|
belongs_to :association do
|
119
119
|
belongs_to :nested
|
data/test/redirect_to_test.rb
CHANGED
@@ -1,63 +1,10 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
|
-
class SuperMachine;
|
4
|
-
def self.human_name; 'Machine'; end
|
5
|
-
end
|
6
|
-
|
7
|
-
# Use this to test blocks with multiple arity in the future.
|
8
|
-
class SuperMachinesController < InheritedResources::Base
|
9
|
-
def create
|
10
|
-
create!('http://test.host/')
|
11
|
-
end
|
12
|
-
|
13
|
-
def update
|
14
|
-
update!('http://test.host/')
|
15
|
-
end
|
16
|
-
|
17
|
-
def destroy
|
18
|
-
destroy!('http://test.host/')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class RedirectToWithArgumentTest < ActionController::TestCase
|
23
|
-
tests SuperMachinesController
|
24
|
-
|
25
|
-
def test_redirect_to_the_given_url_on_create
|
26
|
-
ActiveSupport::Deprecation.expects(:warn).with('create!(redirect_url) is deprecated. Use create!{ redirect_url } instead.', [nil])
|
27
|
-
SuperMachine.stubs(:new).returns(mock_machine(:save => true))
|
28
|
-
@controller.expects(:resource_url).times(0)
|
29
|
-
post :create
|
30
|
-
assert_redirected_to 'http://test.host/'
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_redirect_to_the_given_url_on_update
|
34
|
-
ActiveSupport::Deprecation.expects(:warn).with('update!(redirect_url) is deprecated. Use update!{ redirect_url } instead.', [nil])
|
35
|
-
SuperMachine.stubs(:find).returns(mock_machine(:update_attributes => true))
|
36
|
-
@controller.expects(:resource_url).times(0)
|
37
|
-
put :update
|
38
|
-
assert_redirected_to 'http://test.host/'
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_redirect_to_the_given_url_on_destroy
|
42
|
-
ActiveSupport::Deprecation.expects(:warn).with('destroy!(redirect_url) is deprecated. Use destroy!{ redirect_url } instead.', [nil])
|
43
|
-
SuperMachine.stubs(:find).returns(mock_machine(:destroy => true))
|
44
|
-
@controller.expects(:collection_url).times(0)
|
45
|
-
delete :destroy
|
46
|
-
assert_redirected_to 'http://test.host/'
|
47
|
-
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
def mock_machine(stubs={})
|
51
|
-
@mock_machine ||= mock(stubs)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
3
|
class Machine;
|
56
4
|
def self.human_name; 'Machine'; end
|
57
5
|
end
|
58
6
|
|
59
7
|
class MachinesController < InheritedResources::Base
|
60
|
-
|
61
8
|
def create
|
62
9
|
create!{ complex_url(:create, true, true) }
|
63
10
|
end
|
@@ -106,3 +53,25 @@ class RedirectToWithBlockTest < ActionController::TestCase
|
|
106
53
|
end
|
107
54
|
end
|
108
55
|
|
56
|
+
|
57
|
+
# Use this to test blocks with multiple arity in the future.
|
58
|
+
class SuperMachinesController < InheritedResources::Base
|
59
|
+
defaults :resource_class => Machine
|
60
|
+
|
61
|
+
def create
|
62
|
+
create! do |arg1, arg2, arg3|
|
63
|
+
# nothing
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class RedirectToArityTest < ActionController::TestCase
|
69
|
+
tests SuperMachinesController
|
70
|
+
|
71
|
+
def test_redirect_to_the_given_url_on_create
|
72
|
+
Machine.stubs(:new).returns(:anything)
|
73
|
+
assert_raise ScriptError, /arity/ do
|
74
|
+
post :create
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: josevalim-inherited_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jos\xC3\xA9 Valim"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-05-23 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -28,6 +28,7 @@ files:
|
|
28
28
|
- Rakefile
|
29
29
|
- init.rb
|
30
30
|
- lib/inherited_resources.rb
|
31
|
+
- lib/inherited_resources/actions.rb
|
31
32
|
- lib/inherited_resources/base.rb
|
32
33
|
- lib/inherited_resources/base_helpers.rb
|
33
34
|
- lib/inherited_resources/belongs_to_helpers.rb
|