karsthammer-inherited_resources 1.1.2.1 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG +11 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +86 -0
- data/README.rdoc +78 -50
- data/Rakefile +0 -22
- data/karsthammer-inherited_resources.gemspec +24 -0
- data/lib/inherited_resources/actions.rb +4 -4
- data/lib/inherited_resources/base.rb +11 -10
- data/lib/inherited_resources/base_helpers.rb +40 -3
- data/lib/inherited_resources/class_methods.rb +100 -9
- data/lib/inherited_resources/shallow_helpers.rb +87 -0
- data/lib/inherited_resources/url_helpers.rb +44 -4
- data/lib/inherited_resources/version.rb +1 -1
- data/lib/karsthammer-inherited_resources.rb +7 -2
- data/test/base_test.rb +33 -13
- data/test/belongs_to_test.rb +29 -4
- data/test/belongs_to_with_shallow_test.rb +93 -0
- data/test/class_methods_test.rb +13 -11
- data/test/customized_belongs_to_test.rb +1 -1
- data/test/customized_redirect_to_test.rb +32 -0
- data/test/defaults_test.rb +137 -10
- data/test/locales/en.yml +17 -0
- data/test/nested_belongs_to_with_shallow_test.rb +123 -0
- data/test/nested_model_with_shallow_test.rb +147 -0
- data/test/optional_belongs_to_test.rb +3 -3
- data/test/polymorphic_test.rb +4 -4
- data/test/singleton_test.rb +4 -1
- data/test/test_helper.rb +4 -3
- data/test/url_helpers_test.rb +146 -2
- data/test/views/cars/edit.html.erb +1 -0
- data/test/views/cars/index.html.erb +1 -0
- data/test/views/cars/new.html.erb +1 -0
- data/test/views/cars/show.html.erb +1 -0
- data/test/views/cities/edit.html.erb +1 -0
- data/test/views/cities/index.html.erb +1 -0
- data/test/views/cities/new.html.erb +1 -0
- data/test/views/cities/show.html.erb +1 -0
- data/test/views/comments/edit.html.erb +1 -0
- data/test/views/comments/index.html.erb +1 -0
- data/test/views/comments/new.html.erb +1 -0
- data/test/views/comments/show.html.erb +1 -0
- data/test/views/educations/new.html.erb +0 -0
- data/test/views/employees/edit.html.erb +1 -0
- data/test/views/employees/index.html.erb +1 -0
- data/test/views/employees/new.html.erb +1 -0
- data/test/views/employees/show.html.erb +1 -0
- data/test/views/groups/edit.html.erb +0 -0
- data/test/views/managers/edit.html.erb +1 -0
- data/test/views/managers/new.html.erb +1 -0
- data/test/views/managers/show.html.erb +1 -0
- data/test/views/painters/edit.html.erb +1 -0
- data/test/views/painters/index.html.erb +1 -0
- data/test/views/painters/new.html.erb +1 -0
- data/test/views/painters/show.html.erb +1 -0
- data/test/views/pets/edit.html.erb +1 -0
- data/test/views/pets/index.html.erb +1 -0
- data/test/views/pets/new.html.erb +1 -0
- data/test/views/pets/show.html.erb +1 -0
- data/test/views/plates/edit.html.erb +1 -0
- data/test/views/plates/index.html.erb +1 -0
- data/test/views/plates/new.html.erb +1 -0
- data/test/views/plates/show.html.erb +1 -0
- data/test/views/products/edit.html.erb +1 -0
- data/test/views/products/index.html.erb +1 -0
- data/test/views/products/new.html.erb +1 -0
- data/test/views/products/show.html.erb +1 -0
- data/test/views/professors/edit.html.erb +1 -0
- data/test/views/professors/index.html.erb +1 -0
- data/test/views/professors/new.html.erb +1 -0
- data/test/views/professors/show.html.erb +1 -0
- data/test/views/projects/index.html.erb +1 -0
- data/test/views/projects/index.json.erb +1 -0
- data/test/views/projects/respond_to_skip_default_template.html.erb +1 -0
- data/test/views/projects/respond_with_resource.html.erb +1 -0
- data/test/views/students/edit.html.erb +1 -0
- data/test/views/students/new.html.erb +1 -0
- data/test/views/tags/edit.html.erb +1 -0
- data/test/views/tags/index.html.erb +1 -0
- data/test/views/tags/new.html.erb +1 -0
- data/test/views/tags/show.html.erb +1 -0
- data/test/views/trees/edit.html.erb +1 -0
- data/test/views/trees/index.html.erb +1 -0
- data/test/views/trees/new.html.erb +1 -0
- data/test/views/trees/show.html.erb +1 -0
- data/test/views/university/professors/edit.html.erb +1 -0
- data/test/views/university/professors/index.html.erb +1 -0
- data/test/views/university/professors/new.html.erb +1 -0
- data/test/views/university/professors/show.html.erb +1 -0
- data/test/views/users/create.js.erb +1 -0
- data/test/views/users/destroy.js.erb +1 -0
- data/test/views/users/edit.html.erb +1 -0
- data/test/views/users/index.html.erb +1 -0
- data/test/views/users/new.html.erb +1 -0
- data/test/views/users/show.html.erb +1 -0
- data/test/views/users/update.js.erb +1 -0
- metadata +178 -29
@@ -30,22 +30,31 @@ module InheritedResources
|
|
30
30
|
#
|
31
31
|
# * <tt>:singleton</tt> - Tells if this controller is singleton or not.
|
32
32
|
#
|
33
|
+
# * <tt>:finder</tt> - Specifies which method should be called to instantiate the resource.
|
34
|
+
#
|
35
|
+
# defaults :project, :finder => :find_by_slug
|
36
|
+
#
|
33
37
|
def defaults(options)
|
34
38
|
raise ArgumentError, 'Class method :defaults expects a hash of options.' unless options.is_a? Hash
|
35
39
|
|
36
40
|
options.symbolize_keys!
|
37
41
|
options.assert_valid_keys(:resource_class, :collection_name, :instance_name,
|
38
42
|
:class_name, :route_prefix, :route_collection_name,
|
39
|
-
:route_instance_name, :singleton)
|
43
|
+
:route_instance_name, :singleton, :finder)
|
40
44
|
|
41
|
-
self.resource_class = options
|
42
|
-
self.resource_class = options
|
45
|
+
self.resource_class = options[:resource_class] if options.key?(:resource_class)
|
46
|
+
self.resource_class = options[:class_name].constantize if options.key?(:class_name)
|
43
47
|
|
44
48
|
acts_as_singleton! if options.delete(:singleton)
|
45
49
|
|
46
50
|
config = self.resources_configuration[:self]
|
47
51
|
config[:route_prefix] = options.delete(:route_prefix) if options.key?(:route_prefix)
|
48
52
|
|
53
|
+
if options.key?(:resource_class) or options.key?(:class_name)
|
54
|
+
config[:request_name] = self.resource_class.to_s.underscore.gsub('/', '_')
|
55
|
+
options.delete(:resource_class) and options.delete(:class_name)
|
56
|
+
end
|
57
|
+
|
49
58
|
options.each do |key, value|
|
50
59
|
config[key] = value.to_sym
|
51
60
|
end
|
@@ -132,9 +141,10 @@ module InheritedResources
|
|
132
141
|
options.symbolize_keys!
|
133
142
|
options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param,
|
134
143
|
:finder, :route_name, :collection_name, :singleton,
|
135
|
-
:polymorphic, :optional)
|
144
|
+
:polymorphic, :optional, :shallow)
|
136
145
|
|
137
146
|
optional = options.delete(:optional)
|
147
|
+
shallow = options.delete(:shallow)
|
138
148
|
singleton = options.delete(:singleton)
|
139
149
|
polymorphic = options.delete(:polymorphic)
|
140
150
|
finder = options.delete(:finder)
|
@@ -143,6 +153,7 @@ module InheritedResources
|
|
143
153
|
|
144
154
|
acts_as_singleton! if singleton
|
145
155
|
acts_as_polymorphic! if polymorphic || optional
|
156
|
+
acts_as_shallow! if shallow
|
146
157
|
|
147
158
|
raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
|
148
159
|
raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty?
|
@@ -158,6 +169,8 @@ module InheritedResources
|
|
158
169
|
self.parents_symbols << symbol
|
159
170
|
end
|
160
171
|
|
172
|
+
self.resources_configuration[:self][:shallow] = true if shallow
|
173
|
+
|
161
174
|
config = self.resources_configuration[symbol] = {}
|
162
175
|
|
163
176
|
config[:parent_class] = options.delete(:parent_class) || begin
|
@@ -208,6 +221,40 @@ module InheritedResources
|
|
208
221
|
belongs_to(*symbols << options, &block)
|
209
222
|
end
|
210
223
|
|
224
|
+
# Defines custom restful actions by resource or collection basis.
|
225
|
+
#
|
226
|
+
# custom_actions :resource => [:delete, :transit], :collection => :search
|
227
|
+
#
|
228
|
+
# == Options
|
229
|
+
#
|
230
|
+
# * <tt>:resource</tt> - Allows you to specify resource actions.
|
231
|
+
# custom_actions :resource => :delete
|
232
|
+
# This macro creates 'delete' method in controller and defines
|
233
|
+
# delete_reource_{path,url} helpers. The body of generated 'delete'
|
234
|
+
# method is same as 'show' method. So you can override it if need
|
235
|
+
#
|
236
|
+
# * <tt>:collection</tt> - Allows you to specify collection actions.
|
237
|
+
# custom_actions :collection => :search
|
238
|
+
# This macro creates 'search' method in controller and defines
|
239
|
+
# search_reources_{path,url} helpers. The body of generated 'search'
|
240
|
+
# method is same as 'index' method. So you can override it if need
|
241
|
+
#
|
242
|
+
def custom_actions(options)
|
243
|
+
self.resources_configuration[:self][:custom_actions] = options
|
244
|
+
options.each do | resource_or_collection, actions |
|
245
|
+
[*actions].each do | action |
|
246
|
+
create_custom_action(resource_or_collection, action)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
create_resources_url_helpers!
|
250
|
+
[*options[:resource]].each do | action |
|
251
|
+
helper_method "#{action}_resource_path", "#{action}_resource_url"
|
252
|
+
end
|
253
|
+
[*options[:collection]].each do | action |
|
254
|
+
helper_method "#{action}_resources_path", "#{action}_resources_url"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
211
258
|
private
|
212
259
|
|
213
260
|
def acts_as_singleton! #:nodoc:
|
@@ -225,11 +272,31 @@ module InheritedResources
|
|
225
272
|
end
|
226
273
|
end
|
227
274
|
|
275
|
+
def acts_as_shallow! #:nodoc:
|
276
|
+
include ShallowHelpers
|
277
|
+
end
|
278
|
+
|
228
279
|
# Initialize resources class accessors and set their default values.
|
229
280
|
#
|
230
281
|
def initialize_resources_class_accessors! #:nodoc:
|
231
|
-
#
|
282
|
+
# First priority is the namespaced modek, e.g. User::Group
|
232
283
|
self.resource_class = begin
|
284
|
+
namespaced_class = self.name.sub(/Controller/, '').singularize
|
285
|
+
namespaced_class.constantize
|
286
|
+
rescue NameError
|
287
|
+
nil
|
288
|
+
end
|
289
|
+
|
290
|
+
# Second priority the camelcased c, i.e. UserGroup
|
291
|
+
self.resource_class ||= begin
|
292
|
+
camelcased_class = self.name.sub(/Controller/, '').gsub('::', '').singularize
|
293
|
+
camelcased_class.constantize
|
294
|
+
rescue NameError
|
295
|
+
nil
|
296
|
+
end
|
297
|
+
|
298
|
+
# Otherwise use the Group class, or fail
|
299
|
+
self.resource_class ||= begin
|
233
300
|
class_name = self.controller_name.classify
|
234
301
|
class_name.constantize
|
235
302
|
rescue NameError => e
|
@@ -237,9 +304,16 @@ module InheritedResources
|
|
237
304
|
nil
|
238
305
|
end
|
239
306
|
|
307
|
+
self.parents_symbols = self.parents_symbols.try(:dup) || []
|
308
|
+
|
240
309
|
# Initialize resources configuration hash
|
241
|
-
self.resources_configuration
|
242
|
-
|
310
|
+
self.resources_configuration = self.resources_configuration.try(:dup) || {}
|
311
|
+
self.resources_configuration.each do |key, value|
|
312
|
+
next unless value.is_a?(Hash) || value.is_a?(Array)
|
313
|
+
self.resources_configuration[key] = value.dup
|
314
|
+
end
|
315
|
+
|
316
|
+
config = (self.resources_configuration[:self] ||= {})
|
243
317
|
config[:collection_name] = self.controller_name.to_sym
|
244
318
|
config[:instance_name] = self.controller_name.singularize.to_sym
|
245
319
|
|
@@ -250,9 +324,26 @@ module InheritedResources
|
|
250
324
|
namespaces = self.controller_path.split('/')[0..-2]
|
251
325
|
config[:route_prefix] = namespaces.join('_') unless namespaces.empty?
|
252
326
|
|
327
|
+
# Deal with default request parameters in namespaced controllers, e.g.
|
328
|
+
# Forum::Thread#create will properly pick up the request parameter
|
329
|
+
# which will be forum_thread, and not thread
|
330
|
+
# Additionally make this work orthogonally with instance_name
|
331
|
+
config[:request_name] = self.resource_class.to_s.underscore.gsub('/', '_')
|
332
|
+
|
253
333
|
# Initialize polymorphic, singleton, scopes and belongs_to parameters
|
254
|
-
self.
|
255
|
-
|
334
|
+
polymorphic = self.resources_configuration[:polymorphic] || { :symbols => [], :optional => false }
|
335
|
+
polymorphic[:symbols] = polymorphic[:symbols].dup
|
336
|
+
self.resources_configuration[:polymorphic] = polymorphic
|
337
|
+
end
|
338
|
+
|
339
|
+
def create_custom_action(resource_or_collection, action)
|
340
|
+
class_eval <<-CUSTOM_ACTION, __FILE__, __LINE__
|
341
|
+
def #{action}(options={}, &block)
|
342
|
+
respond_with(*(with_chain(#{resource_or_collection}) << options), &block)
|
343
|
+
end
|
344
|
+
alias :#{action}! :#{action}
|
345
|
+
protected :#{action}!
|
346
|
+
CUSTOM_ACTION
|
256
347
|
end
|
257
348
|
|
258
349
|
# Hook called on inheritance.
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module InheritedResources
|
2
|
+
# = belongs_to
|
3
|
+
#
|
4
|
+
# Let's suppose that we have some tasks that belongs to projects. To specify
|
5
|
+
# this assoication in your controllers, just do:
|
6
|
+
#
|
7
|
+
# class TasksController < InheritedResources::Base
|
8
|
+
# belongs_to :project
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# belongs_to accepts several options to be able to configure the association.
|
12
|
+
# For example, if you want urls like /projects/:project_title/tasks, you
|
13
|
+
# can customize how InheritedResources find your projects:
|
14
|
+
#
|
15
|
+
# class TasksController < InheritedResources::Base
|
16
|
+
# belongs_to :project, :finder => :find_by_title!, :param => :project_title
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# It also accepts :route_name, :parent_class and :instance_name as options.
|
20
|
+
# Check the lib/inherited_resources/class_methods.rb for more.
|
21
|
+
#
|
22
|
+
# = nested_belongs_to
|
23
|
+
#
|
24
|
+
# Now, our Tasks get some Comments and you need to nest even deeper. Good
|
25
|
+
# practices says that you should never nest more than two resources, but sometimes
|
26
|
+
# you have to for security reasons. So this is an example of how you can do it:
|
27
|
+
#
|
28
|
+
# class CommentsController < InheritedResources::Base
|
29
|
+
# nested_belongs_to :project, :task
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# If you need to configure any of these belongs to, you can nested them using blocks:
|
33
|
+
#
|
34
|
+
# class CommentsController < InheritedResources::Base
|
35
|
+
# belongs_to :project, :finder => :find_by_title!, :param => :project_title do
|
36
|
+
# belongs_to :task
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Warning: calling several belongs_to is the same as nesting them:
|
41
|
+
#
|
42
|
+
# class CommentsController < InheritedResources::Base
|
43
|
+
# belongs_to :project
|
44
|
+
# belongs_to :task
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# In other words, the code above is the same as calling nested_belongs_to.
|
48
|
+
#
|
49
|
+
module ShallowHelpers
|
50
|
+
include BelongsToHelpers
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Evaluate the parent given. This is used to nest parents in the
|
55
|
+
# association chain.
|
56
|
+
#
|
57
|
+
|
58
|
+
# Maps parents_symbols to build association chain. In this case, it
|
59
|
+
# simply return the parent_symbols, however on polymorphic belongs to,
|
60
|
+
# it has some customization.
|
61
|
+
#
|
62
|
+
def symbols_for_association_chain #:nodoc:
|
63
|
+
parent_symbols = parents_symbols.dup
|
64
|
+
if parents_symbols.size > 1 && !params[:id]
|
65
|
+
inst_class_name = parent_symbols.pop
|
66
|
+
finder_method = resources_configuration[inst_class_name][:finder] || :find
|
67
|
+
instance = resources_configuration[inst_class_name][:parent_class].send(finder_method, params[resources_configuration[inst_class_name][:param]])
|
68
|
+
load_parents(instance, parent_symbols)
|
69
|
+
end
|
70
|
+
if params[:id]
|
71
|
+
finder_method = resources_configuration[:self][:finder] || :find
|
72
|
+
instance = self.resource_class.send(finder_method, params[:id])
|
73
|
+
load_parents(instance, parent_symbols)
|
74
|
+
end
|
75
|
+
parents_symbols
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_parents(instance, parent_symbols)
|
79
|
+
|
80
|
+
parent_symbols.reverse.each do |parent|
|
81
|
+
instance = instance.send(parent)
|
82
|
+
params[resources_configuration[parent][:param]] = instance.to_param
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -32,6 +32,7 @@ module InheritedResources
|
|
32
32
|
# all created when you inherit.
|
33
33
|
#
|
34
34
|
module UrlHelpers
|
35
|
+
protected
|
35
36
|
|
36
37
|
# This method hard code url helpers in the class.
|
37
38
|
#
|
@@ -39,7 +40,7 @@ module InheritedResources
|
|
39
40
|
# is being processed (and even more cheaper when we are using nested
|
40
41
|
# resources).
|
41
42
|
#
|
42
|
-
# When we are using polymorphic associations, those helpers rely on
|
43
|
+
# When we are using polymorphic associations, those helpers rely on
|
43
44
|
# polymorphic_url Rails helper.
|
44
45
|
#
|
45
46
|
def create_resources_url_helpers!
|
@@ -75,6 +76,7 @@ module InheritedResources
|
|
75
76
|
collection_ivars = resource_ivars.dup
|
76
77
|
collection_segments = resource_segments.dup
|
77
78
|
|
79
|
+
|
78
80
|
# Generate parent url before we add resource instances.
|
79
81
|
unless parents_symbols.empty?
|
80
82
|
generate_url_and_path_helpers nil, :parent, resource_segments, resource_ivars
|
@@ -119,9 +121,9 @@ module InheritedResources
|
|
119
121
|
elsif polymorphic
|
120
122
|
collection_ivars << '(@_resource_class_new ||= resource_class.new)'
|
121
123
|
end
|
122
|
-
|
124
|
+
|
123
125
|
# If route is uncountable then add "_index" suffix to collection index route name
|
124
|
-
#
|
126
|
+
#
|
125
127
|
if !singleton && resource_config[:route_collection_name] == resource_config[:route_instance_name]
|
126
128
|
collection_segments << :index
|
127
129
|
end
|
@@ -130,11 +132,49 @@ module InheritedResources
|
|
130
132
|
generate_url_and_path_helpers :new, :resource, resource_segments, new_ivars || collection_ivars
|
131
133
|
generate_url_and_path_helpers nil, :resource, resource_segments, resource_ivars
|
132
134
|
generate_url_and_path_helpers :edit, :resource, resource_segments, resource_ivars
|
135
|
+
|
136
|
+
if resource_config[:custom_actions]
|
137
|
+
[*resource_config[:custom_actions][:resource]].each do | method |
|
138
|
+
generate_url_and_path_helpers method, :resource, resource_segments, resource_ivars
|
139
|
+
end
|
140
|
+
[*resource_config[:custom_actions][:collection]].each do | method |
|
141
|
+
generate_url_and_path_helpers method, :resources, collection_segments, collection_ivars
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def handle_shallow_resource(prefix, name, segments, ivars) #:nodoc:
|
147
|
+
return segments, ivars unless self.resources_configuration[:self][:shallow]
|
148
|
+
case name
|
149
|
+
when :collection, :resources
|
150
|
+
segments = segments[-2..-1]
|
151
|
+
ivars = [ivars.last]
|
152
|
+
when :resource
|
153
|
+
if prefix == :new
|
154
|
+
segments = segments[-2..-1]
|
155
|
+
ivars = [ivars.last]
|
156
|
+
else
|
157
|
+
segments = [segments.last]
|
158
|
+
ivars = [ivars.last]
|
159
|
+
end
|
160
|
+
when :parent
|
161
|
+
segments = [segments.last]
|
162
|
+
ivars = [ivars.last]
|
163
|
+
end
|
164
|
+
|
165
|
+
segments ||= []
|
166
|
+
|
167
|
+
unless self.resources_configuration[:self][:route_prefix].blank?
|
168
|
+
segments.unshift self.resources_configuration[:self][:route_prefix]
|
169
|
+
end
|
170
|
+
|
171
|
+
return segments, ivars
|
133
172
|
end
|
134
173
|
|
135
174
|
def generate_url_and_path_helpers(prefix, name, resource_segments, resource_ivars) #:nodoc:
|
136
|
-
|
175
|
+
resource_segments, resource_ivars = handle_shallow_resource(prefix, name, resource_segments, resource_ivars)
|
137
176
|
|
177
|
+
ivars = resource_ivars.dup
|
138
178
|
singleton = self.resources_configuration[:self][:singleton]
|
139
179
|
polymorphic = self.parents_symbols.include?(:polymorphic)
|
140
180
|
|
@@ -6,6 +6,7 @@ module InheritedResources
|
|
6
6
|
autoload :Actions, 'inherited_resources/actions'
|
7
7
|
autoload :Base, 'inherited_resources/base'
|
8
8
|
autoload :BaseHelpers, 'inherited_resources/base_helpers'
|
9
|
+
autoload :ShallowHelpers, 'inherited_resources/shallow_helpers'
|
9
10
|
autoload :BelongsToHelpers, 'inherited_resources/belongs_to_helpers'
|
10
11
|
autoload :ClassMethods, 'inherited_resources/class_methods'
|
11
12
|
autoload :DSL, 'inherited_resources/dsl'
|
@@ -21,7 +22,11 @@ module InheritedResources
|
|
21
22
|
|
22
23
|
class Railtie < ::Rails::Railtie
|
23
24
|
config.inherited_resources = InheritedResources
|
24
|
-
config.
|
25
|
+
if config.respond_to?(:app_generators)
|
26
|
+
config.app_generators.scaffold_controller = :inherited_resources_controller
|
27
|
+
else
|
28
|
+
config.generators.scaffold_controller = :inherited_resources_controller
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -34,4 +39,4 @@ class ActionController::Base
|
|
34
39
|
initialize_resources_class_accessors!
|
35
40
|
create_resources_url_helpers!
|
36
41
|
end
|
37
|
-
end
|
42
|
+
end
|
data/test/base_test.rb
CHANGED
@@ -29,34 +29,40 @@ module UserTestHelper
|
|
29
29
|
end
|
30
30
|
|
31
31
|
protected
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
|
33
|
+
def mock_user(expectations={})
|
34
|
+
@mock_user ||= begin
|
35
|
+
user = mock(expectations.except(:errors))
|
36
|
+
user.stubs(:class).returns(User)
|
37
|
+
user.stubs(:errors).returns(expectations.fetch(:errors, {}))
|
38
|
+
user.singleton_class.class_eval do
|
39
|
+
def method_missing(symbol, *arguments, &block)
|
40
|
+
raise NoMethodError.new('this is expected by Array#flatten') if symbol == :to_ary
|
41
|
+
super
|
42
|
+
end
|
39
43
|
end
|
44
|
+
user
|
40
45
|
end
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
class IndexActionBaseTest < ActionController::TestCase
|
44
50
|
include UserTestHelper
|
45
51
|
|
46
52
|
def test_expose_all_users_as_instance_variable
|
47
|
-
User.expects(:
|
53
|
+
User.expects(:scoped).returns([mock_user])
|
48
54
|
get :index
|
49
55
|
assert_equal [mock_user], assigns(:users)
|
50
56
|
end
|
51
57
|
|
52
58
|
def test_apply_scopes_if_method_is_available
|
53
|
-
User.expects(:
|
59
|
+
User.expects(:scoped).returns([mock_user])
|
54
60
|
get :index
|
55
61
|
assert @controller.scopes_applied
|
56
62
|
end
|
57
63
|
|
58
64
|
def test_controller_should_render_index
|
59
|
-
User.stubs(:
|
65
|
+
User.stubs(:scoped).returns([mock_user])
|
60
66
|
get :index
|
61
67
|
assert_response :success
|
62
68
|
assert_equal 'Index HTML', @response.body.strip
|
@@ -64,12 +70,18 @@ class IndexActionBaseTest < ActionController::TestCase
|
|
64
70
|
|
65
71
|
def test_render_all_users_as_xml_when_mime_type_is_xml
|
66
72
|
@request.accept = 'application/xml'
|
67
|
-
User.expects(:
|
68
|
-
|
73
|
+
User.expects(:scoped).returns(collection = [mock_user])
|
74
|
+
collection.expects(:to_xml).returns('Generated XML')
|
69
75
|
get :index
|
70
76
|
assert_response :success
|
71
77
|
assert_equal 'Generated XML', @response.body
|
72
78
|
end
|
79
|
+
|
80
|
+
def test_scoped_is_called_only_when_available
|
81
|
+
User.stubs(:all).returns([mock_user])
|
82
|
+
get :index
|
83
|
+
assert_equal Array, assigns(:users).class
|
84
|
+
end
|
73
85
|
end
|
74
86
|
|
75
87
|
class ShowActionBaseTest < ActionController::TestCase
|
@@ -201,6 +213,14 @@ class UpdateActionBaseTest < ActionController::TestCase
|
|
201
213
|
assert_redirected_to 'http://test.host/'
|
202
214
|
end
|
203
215
|
|
216
|
+
def test_redirect_to_the_users_list_if_show_undefined
|
217
|
+
@controller.class.send(:actions, :all, :except => :show)
|
218
|
+
User.stubs(:find).returns(mock_user(:update_attributes => true))
|
219
|
+
@controller.expects(:collection_url).returns('http://test.host/')
|
220
|
+
put :update
|
221
|
+
assert_redirected_to 'http://test.host/'
|
222
|
+
end
|
223
|
+
|
204
224
|
def test_show_flash_message_when_success
|
205
225
|
User.stubs(:find).returns(mock_user(:update_attributes => true))
|
206
226
|
put :update
|
@@ -229,7 +249,7 @@ end
|
|
229
249
|
|
230
250
|
class DestroyActionBaseTest < ActionController::TestCase
|
231
251
|
include UserTestHelper
|
232
|
-
|
252
|
+
|
233
253
|
def test_the_requested_user_is_destroyed
|
234
254
|
User.expects(:find).with('42').returns(mock_user)
|
235
255
|
mock_user.expects(:destroy).returns(true)
|