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.
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)