karsthammer-inherited_resources 1.1.2.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG +11 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +86 -0
  5. data/README.rdoc +78 -50
  6. data/Rakefile +0 -22
  7. data/karsthammer-inherited_resources.gemspec +24 -0
  8. data/lib/inherited_resources/actions.rb +4 -4
  9. data/lib/inherited_resources/base.rb +11 -10
  10. data/lib/inherited_resources/base_helpers.rb +40 -3
  11. data/lib/inherited_resources/class_methods.rb +100 -9
  12. data/lib/inherited_resources/shallow_helpers.rb +87 -0
  13. data/lib/inherited_resources/url_helpers.rb +44 -4
  14. data/lib/inherited_resources/version.rb +1 -1
  15. data/lib/karsthammer-inherited_resources.rb +7 -2
  16. data/test/base_test.rb +33 -13
  17. data/test/belongs_to_test.rb +29 -4
  18. data/test/belongs_to_with_shallow_test.rb +93 -0
  19. data/test/class_methods_test.rb +13 -11
  20. data/test/customized_belongs_to_test.rb +1 -1
  21. data/test/customized_redirect_to_test.rb +32 -0
  22. data/test/defaults_test.rb +137 -10
  23. data/test/locales/en.yml +17 -0
  24. data/test/nested_belongs_to_with_shallow_test.rb +123 -0
  25. data/test/nested_model_with_shallow_test.rb +147 -0
  26. data/test/optional_belongs_to_test.rb +3 -3
  27. data/test/polymorphic_test.rb +4 -4
  28. data/test/singleton_test.rb +4 -1
  29. data/test/test_helper.rb +4 -3
  30. data/test/url_helpers_test.rb +146 -2
  31. data/test/views/cars/edit.html.erb +1 -0
  32. data/test/views/cars/index.html.erb +1 -0
  33. data/test/views/cars/new.html.erb +1 -0
  34. data/test/views/cars/show.html.erb +1 -0
  35. data/test/views/cities/edit.html.erb +1 -0
  36. data/test/views/cities/index.html.erb +1 -0
  37. data/test/views/cities/new.html.erb +1 -0
  38. data/test/views/cities/show.html.erb +1 -0
  39. data/test/views/comments/edit.html.erb +1 -0
  40. data/test/views/comments/index.html.erb +1 -0
  41. data/test/views/comments/new.html.erb +1 -0
  42. data/test/views/comments/show.html.erb +1 -0
  43. data/test/views/educations/new.html.erb +0 -0
  44. data/test/views/employees/edit.html.erb +1 -0
  45. data/test/views/employees/index.html.erb +1 -0
  46. data/test/views/employees/new.html.erb +1 -0
  47. data/test/views/employees/show.html.erb +1 -0
  48. data/test/views/groups/edit.html.erb +0 -0
  49. data/test/views/managers/edit.html.erb +1 -0
  50. data/test/views/managers/new.html.erb +1 -0
  51. data/test/views/managers/show.html.erb +1 -0
  52. data/test/views/painters/edit.html.erb +1 -0
  53. data/test/views/painters/index.html.erb +1 -0
  54. data/test/views/painters/new.html.erb +1 -0
  55. data/test/views/painters/show.html.erb +1 -0
  56. data/test/views/pets/edit.html.erb +1 -0
  57. data/test/views/pets/index.html.erb +1 -0
  58. data/test/views/pets/new.html.erb +1 -0
  59. data/test/views/pets/show.html.erb +1 -0
  60. data/test/views/plates/edit.html.erb +1 -0
  61. data/test/views/plates/index.html.erb +1 -0
  62. data/test/views/plates/new.html.erb +1 -0
  63. data/test/views/plates/show.html.erb +1 -0
  64. data/test/views/products/edit.html.erb +1 -0
  65. data/test/views/products/index.html.erb +1 -0
  66. data/test/views/products/new.html.erb +1 -0
  67. data/test/views/products/show.html.erb +1 -0
  68. data/test/views/professors/edit.html.erb +1 -0
  69. data/test/views/professors/index.html.erb +1 -0
  70. data/test/views/professors/new.html.erb +1 -0
  71. data/test/views/professors/show.html.erb +1 -0
  72. data/test/views/projects/index.html.erb +1 -0
  73. data/test/views/projects/index.json.erb +1 -0
  74. data/test/views/projects/respond_to_skip_default_template.html.erb +1 -0
  75. data/test/views/projects/respond_with_resource.html.erb +1 -0
  76. data/test/views/students/edit.html.erb +1 -0
  77. data/test/views/students/new.html.erb +1 -0
  78. data/test/views/tags/edit.html.erb +1 -0
  79. data/test/views/tags/index.html.erb +1 -0
  80. data/test/views/tags/new.html.erb +1 -0
  81. data/test/views/tags/show.html.erb +1 -0
  82. data/test/views/trees/edit.html.erb +1 -0
  83. data/test/views/trees/index.html.erb +1 -0
  84. data/test/views/trees/new.html.erb +1 -0
  85. data/test/views/trees/show.html.erb +1 -0
  86. data/test/views/university/professors/edit.html.erb +1 -0
  87. data/test/views/university/professors/index.html.erb +1 -0
  88. data/test/views/university/professors/new.html.erb +1 -0
  89. data/test/views/university/professors/show.html.erb +1 -0
  90. data/test/views/users/create.js.erb +1 -0
  91. data/test/views/users/destroy.js.erb +1 -0
  92. data/test/views/users/edit.html.erb +1 -0
  93. data/test/views/users/index.html.erb +1 -0
  94. data/test/views/users/new.html.erb +1 -0
  95. data/test/views/users/show.html.erb +1 -0
  96. data/test/views/users/update.js.erb +1 -0
  97. 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.delete(:resource_class) if options.key?(:resource_class)
42
- self.resource_class = options.delete(:class_name).constantize if options.key?(:class_name)
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
- # Initialize resource class
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
- config = self.resources_configuration[:self] = {}
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.parents_symbols ||= []
255
- self.resources_configuration[:polymorphic] ||= { :symbols => [], :optional => false }
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
- ivars = resource_ivars.dup
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
 
@@ -1,3 +1,3 @@
1
1
  module InheritedResources
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.2.1'.freeze
3
3
  end
@@ -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.generators.scaffold_controller = :inherited_resources_controller
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
- 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
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(:all).returns([mock_user])
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(:all).returns([mock_user])
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(:all).returns([mock_user])
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(:all).returns(mock_user)
68
- mock_user.expects(:to_xml).returns('Generated XML')
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)