inherited_resources 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/CHANGELOG +103 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +524 -0
  4. data/Rakefile +40 -0
  5. data/lib/inherited_resources.rb +23 -0
  6. data/lib/inherited_resources/actions.rb +79 -0
  7. data/lib/inherited_resources/base.rb +42 -0
  8. data/lib/inherited_resources/base_helpers.rb +363 -0
  9. data/lib/inherited_resources/belongs_to_helpers.rb +89 -0
  10. data/lib/inherited_resources/class_methods.rb +338 -0
  11. data/lib/inherited_resources/dsl.rb +26 -0
  12. data/lib/inherited_resources/dumb_responder.rb +20 -0
  13. data/lib/inherited_resources/has_scope_helpers.rb +83 -0
  14. data/lib/inherited_resources/legacy/respond_to.rb +156 -0
  15. data/lib/inherited_resources/legacy/responder.rb +200 -0
  16. data/lib/inherited_resources/polymorphic_helpers.rb +155 -0
  17. data/lib/inherited_resources/singleton_helpers.rb +95 -0
  18. data/lib/inherited_resources/url_helpers.rb +179 -0
  19. data/test/aliases_test.rb +139 -0
  20. data/test/association_chain_test.rb +125 -0
  21. data/test/base_test.rb +225 -0
  22. data/test/belongs_to_test.rb +87 -0
  23. data/test/class_methods_test.rb +138 -0
  24. data/test/customized_base_test.rb +162 -0
  25. data/test/customized_belongs_to_test.rb +76 -0
  26. data/test/defaults_test.rb +70 -0
  27. data/test/flash_test.rb +88 -0
  28. data/test/has_scope_test.rb +139 -0
  29. data/test/nested_belongs_to_test.rb +108 -0
  30. data/test/optional_belongs_to_test.rb +164 -0
  31. data/test/polymorphic_test.rb +186 -0
  32. data/test/redirect_to_test.rb +51 -0
  33. data/test/respond_to_test.rb +155 -0
  34. data/test/singleton_test.rb +83 -0
  35. data/test/test_helper.rb +38 -0
  36. data/test/url_helpers_test.rb +537 -0
  37. metadata +89 -0
@@ -0,0 +1,125 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Pet
4
+ def self.human_name; 'Pet'; end
5
+ end
6
+
7
+ class Puppet
8
+ def self.human_name; 'Puppet'; end
9
+ end
10
+
11
+ class PetsController < InheritedResources::Base
12
+ attr_accessor :current_user
13
+
14
+ def edit
15
+ @pet = 'new pet'
16
+ edit!
17
+ end
18
+
19
+ protected
20
+ def collection
21
+ @pets ||= end_of_association_chain.all
22
+ end
23
+
24
+ def begin_of_association_chain
25
+ @current_user
26
+ end
27
+ end
28
+
29
+ class BeginOfAssociationChainTest < ActionController::TestCase
30
+ tests PetsController
31
+
32
+ def setup
33
+ @controller.current_user = mock()
34
+ end
35
+
36
+ def test_begin_of_association_chain_is_called_on_index
37
+ @controller.current_user.expects(:pets).returns(Pet)
38
+ Pet.expects(:all).returns(mock_pet)
39
+ get :index
40
+ assert_response :success
41
+ assert_equal 'Index HTML', @response.body.strip
42
+ end
43
+
44
+ def test_begin_of_association_chain_is_called_on_new
45
+ @controller.current_user.expects(:pets).returns(Pet)
46
+ Pet.expects(:build).returns(mock_pet)
47
+ get :new
48
+ assert_response :success
49
+ assert_equal 'New HTML', @response.body.strip
50
+ end
51
+
52
+ def test_begin_of_association_chain_is_called_on_show
53
+ @controller.current_user.expects(:pets).returns(Pet)
54
+ Pet.expects(:find).with('47').returns(mock_pet)
55
+ get :show, :id => '47'
56
+ assert_response :success
57
+ assert_equal 'Show HTML', @response.body.strip
58
+ end
59
+
60
+ def test_instance_variable_should_not_be_set_if_already_defined
61
+ @controller.current_user.expects(:pets).never
62
+ Pet.expects(:find).never
63
+ get :edit
64
+ assert_response :success
65
+ assert_equal 'new pet', assigns(:pet)
66
+ end
67
+
68
+ def test_model_is_not_initialized_with_nil
69
+ @controller.current_user.expects(:pets).returns(Pet)
70
+ Pet.expects(:build).with({}).returns(mock_pet)
71
+ get :new
72
+ assert_equal mock_pet, assigns(:pet)
73
+ end
74
+
75
+ def test_begin_of_association_chain_is_included_in_chain
76
+ @controller.current_user.expects(:pets).returns(Pet)
77
+ Pet.expects(:build).with({}).returns(mock_pet)
78
+ get :new
79
+ assert_equal [@controller.current_user], @controller.send(:association_chain)
80
+ end
81
+
82
+ protected
83
+ def mock_pet(stubs={})
84
+ @mock_pet ||= mock(stubs)
85
+ end
86
+
87
+ end
88
+
89
+ class PuppetsController < InheritedResources::Base
90
+ optional_belongs_to :pet
91
+ end
92
+
93
+ class AssociationChainTest < ActionController::TestCase
94
+ tests PuppetsController
95
+
96
+ def setup
97
+ @controller.stubs(:resource_url).returns('/')
98
+ @controller.stubs(:collection_url).returns('/')
99
+ end
100
+
101
+ def test_parent_is_added_to_association_chain
102
+ Pet.expects(:find).with('37').returns(mock_pet)
103
+ mock_pet.expects(:puppets).returns(Puppet)
104
+ Puppet.expects(:find).with('42').returns(mock_puppet)
105
+ mock_puppet.expects(:destroy)
106
+ delete :destroy, :id => '42', :pet_id => '37'
107
+ assert_equal [mock_pet], @controller.send(:association_chain)
108
+ end
109
+
110
+ def test_parent_is_added_to_association_chain_if_not_available
111
+ Puppet.expects(:find).with('42').returns(mock_puppet)
112
+ mock_puppet.expects(:destroy)
113
+ delete :destroy, :id => '42'
114
+ assert_equal [], @controller.send(:association_chain)
115
+ end
116
+
117
+ protected
118
+ def mock_pet(stubs={})
119
+ @mock_pet ||= mock(stubs)
120
+ end
121
+
122
+ def mock_puppet(stubs={})
123
+ @mock_puppet ||= mock(stubs)
124
+ end
125
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,225 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class User
4
+ def self.human_name; 'User'; end
5
+ end
6
+
7
+ class AccountsController < InheritedResources::Base
8
+ end
9
+
10
+ class UsersController < AccountsController
11
+ respond_to :html, :xml
12
+ end
13
+
14
+ module UserTestHelper
15
+ def setup
16
+ @controller = UsersController.new
17
+ @controller.request = @request = ActionController::TestRequest.new
18
+ @controller.response = @response = ActionController::TestResponse.new
19
+ end
20
+
21
+ protected
22
+ def mock_user(stubs={})
23
+ @mock_user ||= mock(stubs)
24
+ end
25
+ end
26
+
27
+ class IndexActionBaseTest < ActionController::TestCase
28
+ include UserTestHelper
29
+
30
+ def test_expose_all_users_as_instance_variable
31
+ User.expects(:find).with(:all).returns([mock_user])
32
+ get :index
33
+ assert_equal [mock_user], assigns(:users)
34
+ end
35
+
36
+ def test_controller_should_render_index
37
+ User.stubs(:find).returns([mock_user])
38
+ get :index
39
+ assert_response :success
40
+ assert_equal 'Index HTML', @response.body.strip
41
+ end
42
+
43
+ def test_render_all_users_as_xml_when_mime_type_is_xml
44
+ @request.accept = 'application/xml'
45
+ User.expects(:find).with(:all).returns(mock_user)
46
+ mock_user.expects(:to_xml).returns('Generated XML')
47
+ get :index
48
+ assert_response :success
49
+ assert_equal 'Generated XML', @response.body
50
+ end
51
+ end
52
+
53
+ class ShowActionBaseTest < ActionController::TestCase
54
+ include UserTestHelper
55
+
56
+ def test_expose_the_resquested_user
57
+ User.expects(:find).with('42').returns(mock_user)
58
+ get :show, :id => '42'
59
+ assert_equal mock_user, assigns(:user)
60
+ end
61
+
62
+ def test_controller_should_render_show
63
+ User.stubs(:find).returns(mock_user)
64
+ get :show
65
+ assert_response :success
66
+ assert_equal 'Show HTML', @response.body.strip
67
+ end
68
+
69
+ def test_render_exposed_user_as_xml_when_mime_type_is_xml
70
+ @request.accept = 'application/xml'
71
+ User.expects(:find).with('42').returns(mock_user)
72
+ mock_user.expects(:to_xml).returns("Generated XML")
73
+ get :show, :id => '42'
74
+ assert_response :success
75
+ assert_equal 'Generated XML', @response.body
76
+ end
77
+ end
78
+
79
+ class NewActionBaseTest < ActionController::TestCase
80
+ include UserTestHelper
81
+
82
+ def test_expose_a_new_user
83
+ User.expects(:new).returns(mock_user)
84
+ get :new
85
+ assert_equal mock_user, assigns(:user)
86
+ end
87
+
88
+ def test_controller_should_render_new
89
+ User.stubs(:new).returns(mock_user)
90
+ get :new
91
+ assert_response :success
92
+ assert_equal 'New HTML', @response.body.strip
93
+ end
94
+
95
+ def test_render_exposed_a_new_user_as_xml_when_mime_type_is_xml
96
+ @request.accept = 'application/xml'
97
+ User.expects(:new).returns(mock_user)
98
+ mock_user.expects(:to_xml).returns("Generated XML")
99
+ get :new
100
+ assert_response :success
101
+ assert_equal 'Generated XML', @response.body
102
+ end
103
+ end
104
+
105
+ class EditActionBaseTest < ActionController::TestCase
106
+ include UserTestHelper
107
+
108
+ def test_expose_the_resquested_user
109
+ User.expects(:find).with('42').returns(mock_user)
110
+ get :edit, :id => '42'
111
+ assert_response :success
112
+ assert_equal mock_user, assigns(:user)
113
+ end
114
+
115
+ def test_controller_should_render_edit
116
+ User.stubs(:find).returns(mock_user)
117
+ get :edit
118
+ assert_response :success
119
+ assert_equal 'Edit HTML', @response.body.strip
120
+ end
121
+ end
122
+
123
+ class CreateActionBaseTest < ActionController::TestCase
124
+ include UserTestHelper
125
+
126
+ def test_expose_a_newly_create_user_when_saved_with_success
127
+ User.expects(:new).with({'these' => 'params'}).returns(mock_user(:save => true))
128
+ post :create, :user => {:these => 'params'}
129
+ assert_equal mock_user, assigns(:user)
130
+ end
131
+
132
+ def test_redirect_to_the_created_user
133
+ User.stubs(:new).returns(mock_user(:save => true))
134
+ @controller.expects(:resource_url).returns('http://test.host/')
135
+ post :create
136
+ assert_redirected_to 'http://test.host/'
137
+ end
138
+
139
+ def test_show_flash_message_when_success
140
+ User.stubs(:new).returns(mock_user(:save => true))
141
+ post :create
142
+ assert_equal flash[:notice], 'User was successfully created.'
143
+ end
144
+
145
+ def test_render_new_template_when_user_cannot_be_saved
146
+ User.stubs(:new).returns(mock_user(:save => false, :errors => {:some => :error}))
147
+ post :create
148
+ assert_response :success
149
+ assert_equal "New HTML", @response.body.strip
150
+ end
151
+
152
+ def test_dont_show_flash_message_when_user_cannot_be_saved
153
+ User.stubs(:new).returns(mock_user(:save => false, :errors => {:some => :error}))
154
+ post :create
155
+ assert flash.empty?
156
+ end
157
+ end
158
+
159
+ class UpdateActionBaseTest < ActionController::TestCase
160
+ include UserTestHelper
161
+
162
+ def test_update_the_requested_object
163
+ User.expects(:find).with('42').returns(mock_user)
164
+ mock_user.expects(:update_attributes).with({'these' => 'params'}).returns(true)
165
+ put :update, :id => '42', :user => {:these => 'params'}
166
+ assert_equal mock_user, assigns(:user)
167
+ end
168
+
169
+ def test_redirect_to_the_created_user
170
+ User.stubs(:find).returns(mock_user(:update_attributes => true))
171
+ @controller.expects(:resource_url).returns('http://test.host/')
172
+ put :update
173
+ assert_redirected_to 'http://test.host/'
174
+ end
175
+
176
+ def test_show_flash_message_when_success
177
+ User.stubs(:find).returns(mock_user(:update_attributes => true))
178
+ put :update
179
+ assert_equal flash[:notice], 'User was successfully updated.'
180
+ end
181
+
182
+ def test_render_edit_template_when_user_cannot_be_saved
183
+ User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => {:some => :error}))
184
+ put :update
185
+ assert_response :success
186
+ assert_equal "Edit HTML", @response.body.strip
187
+ end
188
+
189
+ def test_dont_show_flash_message_when_user_cannot_be_saved
190
+ User.stubs(:find).returns(mock_user(:update_attributes => false, :errors => {:some => :error}))
191
+ put :update
192
+ assert flash.empty?
193
+ end
194
+ end
195
+
196
+ class DestroyActionBaseTest < ActionController::TestCase
197
+ include UserTestHelper
198
+
199
+ def test_the_requested_user_is_destroyed
200
+ User.expects(:find).with('42').returns(mock_user)
201
+ mock_user.expects(:destroy)
202
+ delete :destroy, :id => '42'
203
+ assert_equal mock_user, assigns(:user)
204
+ end
205
+
206
+ def test_show_flash_message_when_user_can_be_deleted
207
+ User.stubs(:find).returns(mock_user(:destroy => true))
208
+ delete :destroy
209
+ assert_equal flash[:notice], 'User was successfully destroyed.'
210
+ end
211
+
212
+ def test_show_flash_message_when_cannot_be_deleted
213
+ User.stubs(:find).returns(mock_user(:destroy => false))
214
+ delete :destroy
215
+ assert_equal flash[:error], 'User could not be destroyed.'
216
+ end
217
+
218
+ def test_redirects_to_users_list
219
+ User.stubs(:find).returns(mock_user(:destroy => true))
220
+ @controller.expects(:collection_url).returns('http://test.host/')
221
+ delete :destroy
222
+ assert_redirected_to 'http://test.host/'
223
+ end
224
+ end
225
+
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Post
4
+ end
5
+
6
+ class Comment
7
+ def self.human_name; 'Comment'; end
8
+ end
9
+
10
+ class CommentsController < InheritedResources::Base
11
+ belongs_to :post
12
+ end
13
+
14
+ class BelongsToTest < ActionController::TestCase
15
+ tests CommentsController
16
+
17
+ def setup
18
+ Post.expects(:find).with('37').returns(mock_post)
19
+ mock_post.expects(:comments).returns(Comment)
20
+
21
+ @controller.stubs(:resource_url).returns('/')
22
+ @controller.stubs(:collection_url).returns('/')
23
+ end
24
+
25
+ def test_expose_all_comments_as_instance_variable_on_index
26
+ Comment.expects(:find).with(:all).returns([mock_comment])
27
+ get :index, :post_id => '37'
28
+ assert_equal mock_post, assigns(:post)
29
+ assert_equal [mock_comment], assigns(:comments)
30
+ end
31
+
32
+ def test_expose_the_resquested_comment_on_show
33
+ Comment.expects(:find).with('42').returns(mock_comment)
34
+ get :show, :id => '42', :post_id => '37'
35
+ assert_equal mock_post, assigns(:post)
36
+ assert_equal mock_comment, assigns(:comment)
37
+ end
38
+
39
+ def test_expose_a_new_comment_on_new
40
+ Comment.expects(:build).returns(mock_comment)
41
+ get :new, :post_id => '37'
42
+ assert_equal mock_post, assigns(:post)
43
+ assert_equal mock_comment, assigns(:comment)
44
+ end
45
+
46
+ def test_expose_the_resquested_comment_on_edit
47
+ Comment.expects(:find).with('42').returns(mock_comment)
48
+ get :edit, :id => '42', :post_id => '37'
49
+ assert_equal mock_post, assigns(:post)
50
+ assert_equal mock_comment, assigns(:comment)
51
+ end
52
+
53
+ def test_expose_a_newly_create_comment_on_create
54
+ Comment.expects(:build).with({'these' => 'params'}).returns(mock_comment(:save => true))
55
+ post :create, :post_id => '37', :comment => {:these => 'params'}
56
+ assert_equal mock_post, assigns(:post)
57
+ assert_equal mock_comment, assigns(:comment)
58
+ end
59
+
60
+ def test_update_the_requested_object_on_update
61
+ Comment.expects(:find).with('42').returns(mock_comment)
62
+ mock_comment.expects(:update_attributes).with({'these' => 'params'}).returns(true)
63
+ put :update, :id => '42', :post_id => '37', :comment => {:these => 'params'}
64
+ assert_equal mock_post, assigns(:post)
65
+ assert_equal mock_comment, assigns(:comment)
66
+ end
67
+
68
+ def test_the_resquested_comment_is_destroyed_on_destroy
69
+ Comment.expects(:find).with('42').returns(mock_comment)
70
+ mock_comment.expects(:destroy)
71
+ delete :destroy, :id => '42', :post_id => '37'
72
+ assert_equal mock_post, assigns(:post)
73
+ assert_equal mock_comment, assigns(:comment)
74
+ end
75
+
76
+ protected
77
+
78
+ def mock_post(stubs={})
79
+ @mock_post ||= mock(stubs)
80
+ end
81
+
82
+ def mock_comment(stubs={})
83
+ @mock_comment ||= mock(stubs)
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,138 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Book; end
4
+ class Folder; end
5
+
6
+ class BooksController < InheritedResources::Base
7
+ actions :index, :show
8
+ end
9
+
10
+ class ReadersController < InheritedResources::Base
11
+ actions :all, :except => [ :edit, :update ]
12
+ end
13
+
14
+ class FoldersController < InheritedResources::Base
15
+ end
16
+
17
+ class Dean
18
+ def self.human_name; 'Dean'; end
19
+ end
20
+
21
+ class SchoolsController < InheritedResources::Base
22
+ has_scope :by_city
23
+ has_scope :featured, :boolean => true, :only => :index, :as => :by_featured
24
+ end
25
+
26
+ class DeansController < InheritedResources::Base
27
+ belongs_to :school
28
+ end
29
+
30
+
31
+ class ActionsClassMethodTest < ActiveSupport::TestCase
32
+ def test_actions_are_undefined
33
+ action_methods = BooksController.send(:action_methods)
34
+ assert_equal 2, action_methods.size
35
+
36
+ ['index', 'show'].each do |action|
37
+ assert action_methods.include? action
38
+ end
39
+ end
40
+
41
+ def test_actions_are_undefined_when_except_option_is_given
42
+ action_methods = ReadersController.send(:action_methods)
43
+ assert_equal 5, action_methods.size
44
+
45
+ ['index', 'new', 'show', 'create', 'destroy'].each do |action|
46
+ assert action_methods.include? action
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+ class DefaultsClassMethodTest < ActiveSupport::TestCase
53
+ def test_resource_class_is_set_to_nil_when_resource_model_cannot_be_found
54
+ assert_nil ReadersController.send(:resource_class)
55
+ end
56
+
57
+ def test_defaults_are_set
58
+ assert Folder, FoldersController.send(:resource_class)
59
+ assert :folder, FoldersController.send(:resources_configuration)[:self][:instance_name]
60
+ assert :folders, FoldersController.send(:resources_configuration)[:self][:collection_name]
61
+ end
62
+
63
+ def test_defaults_can_be_overwriten
64
+ BooksController.send(:defaults, :resource_class => String, :instance_name => 'string', :collection_name => 'strings')
65
+
66
+ assert String, BooksController.send(:resource_class)
67
+ assert :string, BooksController.send(:resources_configuration)[:self][:instance_name]
68
+ assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name]
69
+
70
+ BooksController.send(:defaults, :class_name => 'Fixnum', :instance_name => :fixnum, :collection_name => :fixnums)
71
+
72
+ assert String, BooksController.send(:resource_class)
73
+ assert :string, BooksController.send(:resources_configuration)[:self][:instance_name]
74
+ assert :strings, BooksController.send(:resources_configuration)[:self][:collection_name]
75
+ end
76
+
77
+ def test_defaults_raises_invalid_key
78
+ assert_raise ArgumentError do
79
+ BooksController.send(:defaults, :boom => String)
80
+ end
81
+ end
82
+
83
+ def test_url_helpers_are_recreated_when_defaults_change
84
+ BooksController.expects(:create_resources_url_helpers!).returns(true).once
85
+ BooksController.send(:defaults, :instance_name => 'string', :collection_name => 'strings')
86
+ end
87
+ end
88
+
89
+ class BelongsToErrorsTest < ActiveSupport::TestCase
90
+ def test_belongs_to_raise_errors_with_invalid_arguments
91
+ assert_raise ArgumentError do
92
+ DeansController.send(:belongs_to)
93
+ end
94
+
95
+ assert_raise ArgumentError do
96
+ DeansController.send(:belongs_to, :nice, :invalid_key => '')
97
+ end
98
+ end
99
+
100
+ def test_belongs_to_raises_an_error_when_multiple_associations_are_given_with_options
101
+ assert_raise ArgumentError do
102
+ DeansController.send(:belongs_to, :arguments, :with_options, :parent_class => Professor)
103
+ end
104
+ end
105
+
106
+ def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_block
107
+ DeansController.expects(:create_resources_url_helpers!).returns(true).once
108
+ DeansController.send(:belongs_to, :school) do
109
+ belongs_to :association
110
+ end
111
+ ensure
112
+ DeansController.send(:parents_symbols=, [:school])
113
+ end
114
+
115
+ def test_url_helpers_are_recreated_just_once_when_belongs_to_is_called_with_multiple_blocks
116
+ DeansController.expects(:create_resources_url_helpers!).returns(true).once
117
+ DeansController.send(:belongs_to, :school) do
118
+ belongs_to :association do
119
+ belongs_to :nested
120
+ end
121
+ end
122
+ ensure
123
+ DeansController.send(:parents_symbols=, [:school])
124
+ end
125
+ end
126
+
127
+ class HasScopeClassMethods < ActiveSupport::TestCase
128
+ def test_scope_configuration_is_stored_as_hashes
129
+ config = SchoolsController.send(:scopes_configuration)
130
+
131
+ assert config.key?(:by_city)
132
+ assert config.key?(:featured)
133
+
134
+ assert_equal config[:by_city], { :as => :by_city, :only => [], :except => [] }
135
+ assert_equal config[:featured], { :as => :by_featured, :only => [ :index ], :except => [], :boolean => true }
136
+ end
137
+ end
138
+