josevalim-inherited_resources 0.3 → 0.4

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.
@@ -0,0 +1,111 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Factory; end
4
+ class Company; end
5
+
6
+ class Employee
7
+ def self.human_name; 'Employee'; end
8
+ end
9
+
10
+ class EmployeesController < InheritedResources::Base
11
+ belongs_to :factory, :company, :polymorphic => true
12
+ end
13
+
14
+ class PolymorphicTest < TEST_CLASS
15
+
16
+ def setup
17
+ @controller = EmployeesController.new
18
+ @controller.request = @request = ActionController::TestRequest.new
19
+ @controller.response = @response = ActionController::TestResponse.new
20
+ end
21
+
22
+ def test_expose_all_employees_as_instance_variable_on_index
23
+ Factory.expects(:find).with('37').returns(mock_factory)
24
+ mock_factory.expects(:employees).returns(Employee)
25
+ Employee.expects(:find).with(:all).returns([mock_employee])
26
+ get :index, :factory_id => '37'
27
+ assert_equal mock_factory, assigns(:factory)
28
+ assert_equal [mock_employee], assigns(:employees)
29
+ end
30
+
31
+ def test_expose_the_resquested_employee_on_show
32
+ Factory.expects(:find).with('37').returns(mock_factory)
33
+ mock_factory.expects(:employees).returns(Employee)
34
+ Employee.expects(:find).with('42').returns(mock_employee)
35
+ get :show, :id => '42', :factory_id => '37'
36
+ assert_equal mock_factory, assigns(:factory)
37
+ assert_equal mock_employee, assigns(:employee)
38
+ end
39
+
40
+ def test_expose_a_new_employee_on_new
41
+ Factory.expects(:find).with('37').returns(mock_factory)
42
+ mock_factory.expects(:employees).returns(Employee)
43
+ Employee.expects(:build).returns(mock_employee)
44
+ get :new, :factory_id => '37'
45
+ assert_equal mock_factory, assigns(:factory)
46
+ assert_equal mock_employee, assigns(:employee)
47
+ end
48
+
49
+ def test_expose_the_resquested_employee_on_edit
50
+ Factory.expects(:find).with('37').returns(mock_factory)
51
+ mock_factory.expects(:employees).returns(Employee)
52
+ Employee.expects(:find).with('42').returns(mock_employee)
53
+ get :edit, :id => '42', :factory_id => '37'
54
+ assert_equal mock_factory, assigns(:factory)
55
+ assert_equal mock_employee, assigns(:employee)
56
+ assert_response :success
57
+ end
58
+
59
+ def test_expose_a_newly_create_employee_on_create
60
+ Factory.expects(:find).with('37').returns(mock_factory)
61
+ mock_factory.expects(:employees).returns(Employee)
62
+ Employee.expects(:build).with({'these' => 'params'}).returns(mock_employee(:save => true))
63
+ post :create, :factory_id => '37', :employee => {:these => 'params'}
64
+ assert_equal mock_factory, assigns(:factory)
65
+ assert_equal mock_employee, assigns(:employee)
66
+ end
67
+
68
+ def test_update_the_requested_object_on_update
69
+ Factory.expects(:find).with('37').returns(mock_factory)
70
+ mock_factory.expects(:employees).returns(Employee)
71
+ Employee.expects(:find).with('42').returns(mock_employee)
72
+ mock_employee.expects(:update_attributes).with({'these' => 'params'}).returns(true)
73
+ put :update, :id => '42', :factory_id => '37', :employee => {:these => 'params'}
74
+ assert_equal mock_factory, assigns(:factory)
75
+ assert_equal mock_employee, assigns(:employee)
76
+ end
77
+
78
+ def test_the_resquested_employee_is_destroyed_on_destroy
79
+ Factory.expects(:find).with('37').returns(mock_factory)
80
+ mock_factory.expects(:employees).returns(Employee)
81
+ Employee.expects(:find).with('42').returns(mock_employee)
82
+ mock_employee.expects(:destroy)
83
+ delete :destroy, :id => '42', :factory_id => '37'
84
+ assert_equal mock_factory, assigns(:factory)
85
+ assert_equal mock_employee, assigns(:employee)
86
+ end
87
+
88
+ def test_polymorphic_helpers
89
+ new_factory = Factory.new
90
+ Factory.expects(:find).with('37').returns(new_factory)
91
+ new_factory.expects(:employees).returns(Employee)
92
+ Employee.expects(:find).with(:all).returns([mock_employee])
93
+ get :index, :factory_id => '37'
94
+
95
+ assert @controller.send(:parent?)
96
+ assert_equal :factory, assigns(:parent_type)
97
+ assert_equal :factory, @controller.send(:parent_type)
98
+ assert_equal Factory, @controller.send(:parent_class)
99
+ assert_equal new_factory, assigns(:factory)
100
+ assert_equal new_factory, @controller.send(:parent)
101
+ end
102
+
103
+ protected
104
+ def mock_factory(stubs={})
105
+ @mock_factory ||= mock(stubs)
106
+ end
107
+
108
+ def mock_employee(stubs={})
109
+ @mock_employee ||= mock(stubs)
110
+ end
111
+ end
@@ -0,0 +1,83 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ # This test file is instead to test the how controller flow and actions
4
+ # using a belongs_to association. This is done using mocks a la rspec.
5
+ #
6
+ class Store
7
+ end
8
+
9
+ class Manager
10
+ def self.human_name; 'Manager'; end
11
+ end
12
+
13
+ class ManagersController < InheritedResources::Base
14
+ belongs_to :store, :singleton => true
15
+ end
16
+
17
+ class SingletonTest < TEST_CLASS
18
+
19
+ def setup
20
+ @controller = ManagersController.new
21
+ @controller.request = @request = ActionController::TestRequest.new
22
+ @controller.response = @response = ActionController::TestResponse.new
23
+ end
24
+
25
+ def test_expose_the_resquested_manager_on_show
26
+ Store.expects(:find).with('37').returns(mock_store)
27
+ mock_store.expects(:manager).returns(mock_manager)
28
+ get :show, :store_id => '37'
29
+ assert_equal mock_store, assigns(:store)
30
+ assert_equal mock_manager, assigns(:manager)
31
+ end
32
+
33
+ def test_expose_a_new_manager_on_new
34
+ Store.expects(:find).with('37').returns(mock_store)
35
+ mock_store.expects(:build_manager).returns(mock_manager)
36
+ get :new, :store_id => '37'
37
+ assert_equal mock_store, assigns(:store)
38
+ assert_equal mock_manager, assigns(:manager)
39
+ end
40
+
41
+ def test_expose_the_resquested_manager_on_edit
42
+ Store.expects(:find).with('37').returns(mock_store)
43
+ mock_store.expects(:manager).returns(mock_manager)
44
+ get :edit, :store_id => '37'
45
+ assert_equal mock_store, assigns(:store)
46
+ assert_equal mock_manager, assigns(:manager)
47
+ assert_response :success
48
+ end
49
+
50
+ def test_expose_a_newly_create_manager_on_create
51
+ Store.expects(:find).with('37').returns(mock_store)
52
+ mock_store.expects(:build_manager).with({'these' => 'params'}).returns(mock_manager(:save => true))
53
+ post :create, :store_id => '37', :manager => {:these => 'params'}
54
+ assert_equal mock_store, assigns(:store)
55
+ assert_equal mock_manager, assigns(:manager)
56
+ end
57
+
58
+ def test_update_the_requested_object_on_update
59
+ Store.expects(:find).with('37').returns(mock_store(:manager => mock_manager))
60
+ mock_manager.expects(:update_attributes).with({'these' => 'params'}).returns(true)
61
+ put :update, :store_id => '37', :manager => {:these => 'params'}
62
+ assert_equal mock_store, assigns(:store)
63
+ assert_equal mock_manager, assigns(:manager)
64
+ end
65
+
66
+ def test_the_resquested_manager_is_destroyed_on_destroy
67
+ Store.expects(:find).with('37').returns(mock_store)
68
+ mock_store.expects(:manager).returns(mock_manager)
69
+ mock_manager.expects(:destroy)
70
+ delete :destroy, :store_id => '37'
71
+ assert_equal mock_store, assigns(:store)
72
+ assert_equal mock_manager, assigns(:manager)
73
+ end
74
+
75
+ protected
76
+ def mock_store(stubs={})
77
+ @mock_store ||= mock(stubs)
78
+ end
79
+
80
+ def mock_manager(stubs={})
81
+ @mock_manager ||= mock(stubs)
82
+ end
83
+ end
@@ -30,7 +30,7 @@ end
30
30
 
31
31
  class Bed; end
32
32
  class BedsController < InheritedResources::Base
33
- belongs_to :house, :building, :polymorphic => true
33
+ belongs_to :house, :building, :polymorphic => true, :optional => true
34
34
  end
35
35
 
36
36
  class Dish; end
@@ -182,7 +182,7 @@ class UrlHelpersTest < ActiveSupport::TestCase
182
182
  end
183
183
  end
184
184
 
185
- def test_url_helpers_on_singletons
185
+ def test_url_helpers_on_singletons_with_belongs_to
186
186
  controller = OwnersController.new
187
187
  controller.instance_variable_set('@house', :house)
188
188
  controller.instance_variable_set('@owner', :owner)
@@ -204,7 +204,7 @@ class UrlHelpersTest < ActiveSupport::TestCase
204
204
  end
205
205
  end
206
206
 
207
- def test_url_helpers_on_house_polymorphic_belongs_to
207
+ def test_url_helpers_on_polymorphic_belongs_to
208
208
  house = House.new
209
209
  bed = Bed.new
210
210
 
@@ -277,7 +277,7 @@ class UrlHelpersTest < ActiveSupport::TestCase
277
277
  end
278
278
 
279
279
  def test_url_helpers_on_singleton_nested_polymorphic_belongs_to
280
- # Thus must not be usefull in singleton controllers...
280
+ # This must not be usefull in singleton controllers...
281
281
  # Center.new
282
282
  house = House.new
283
283
  table = Table.new
@@ -308,4 +308,36 @@ class UrlHelpersTest < ActiveSupport::TestCase
308
308
  end
309
309
  end
310
310
 
311
+ def test_url_helpers_on_optional_polymorphic_belongs_to
312
+ bed = Bed.new
313
+ new_bed = Bed.new
314
+ Bed.stubs(:new).returns(new_bed)
315
+ new_bed.stubs(:new_record?).returns(true)
316
+
317
+ controller = BedsController.new
318
+ controller.instance_variable_set('@parent_type', nil)
319
+ controller.instance_variable_set('@bed', bed)
320
+
321
+ [:url, :path].each do |path_or_url|
322
+ controller.expects("beds_#{path_or_url}").with().once
323
+ controller.send("collection_#{path_or_url}")
324
+
325
+ controller.expects("bed_#{path_or_url}").with(bed).once
326
+ controller.send("resource_#{path_or_url}")
327
+
328
+ controller.expects("new_bed_#{path_or_url}").with().once
329
+ controller.send("new_resource_#{path_or_url}")
330
+
331
+ controller.expects("edit_bed_#{path_or_url}").with(bed).once
332
+ controller.send("edit_resource_#{path_or_url}")
333
+ end
334
+
335
+ # Testing if it accepts args...
336
+ controller.expects("polymorphic_url").with([:arg]).once
337
+ controller.send("resource_url", :arg)
338
+
339
+ controller.expects("edit_polymorphic_url").with([:arg]).once
340
+ controller.send("edit_resource_url", :arg)
341
+ end
342
+
311
343
  end
@@ -0,0 +1 @@
1
+ Edit HTML
@@ -0,0 +1 @@
1
+ Index HTML
@@ -0,0 +1 @@
1
+ New HTML
@@ -0,0 +1 @@
1
+ Show HTML
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: josevalim-inherited_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.3"
4
+ version: "0.4"
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Jos\xC3\xA9 Valim"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-12 00:00:00 -08:00
12
+ date: 2009-02-15 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,7 +30,6 @@ files:
30
30
  - lib/inherited_resources.rb
31
31
  - lib/inherited_resources/base.rb
32
32
  - lib/inherited_resources/base_helpers.rb
33
- - lib/inherited_resources/belongs_to.rb
34
33
  - lib/inherited_resources/belongs_to_helpers.rb
35
34
  - lib/inherited_resources/class_methods.rb
36
35
  - lib/inherited_resources/dumb_responder.rb
@@ -69,16 +68,16 @@ test_files:
69
68
  - test/aliases_test.rb
70
69
  - test/base_helpers_test.rb
71
70
  - test/base_test.rb
72
- - test/belongs_to_base_test.rb
73
71
  - test/belongs_to_test.rb
74
72
  - test/class_methods_test.rb
75
- - test/fixtures/en.yml
76
73
  - test/nested_belongs_to_test.rb
77
- - test/polymorphic_base_test.rb
74
+ - test/optional_belongs_to_test.rb
75
+ - test/polymorphic_test.rb
78
76
  - test/respond_to_test.rb
79
- - test/singleton_base_test.rb
77
+ - test/singleton_test.rb
80
78
  - test/test_helper.rb
81
79
  - test/url_helpers_test.rb
80
+ - test/fixtures/en.yml
82
81
  - test/views/cities/edit.html.erb
83
82
  - test/views/cities/index.html.erb
84
83
  - test/views/cities/new.html.erb
@@ -95,6 +94,10 @@ test_files:
95
94
  - test/views/managers/new.html.erb
96
95
  - test/views/managers/show.html.erb
97
96
  - test/views/pets/edit.html.erb
97
+ - test/views/products/edit.html.erb
98
+ - test/views/products/index.html.erb
99
+ - test/views/products/new.html.erb
100
+ - test/views/products/show.html.erb
98
101
  - test/views/professors/edit.html.erb
99
102
  - test/views/professors/index.html.erb
100
103
  - test/views/professors/new.html.erb
@@ -1,227 +0,0 @@
1
- # = belongs_to
2
- #
3
- # This allows you to specify to belongs_to in your controller. You might use
4
- # this when you are having nested resources in your routes:
5
- #
6
- # class TasksController < InheritedResources::Base
7
- # belongs_to :project
8
- # end
9
- #
10
- # This will do all magic assuming some defaults. It assumes that your URL to
11
- # access those tasks are:
12
- #
13
- # /projects/:project_id/tasks
14
- #
15
- # But all defaults are configurable. The options are:
16
- #
17
- # * :parent_class => Allows you to specify what is the parent class.
18
- #
19
- # belongs_to :project, :parent_class => AdminProject
20
- #
21
- # * :class_name => Also allows you to specify the parent class, but you should
22
- # give a string. Added for ActiveRecord belongs to compatibility.
23
- #
24
- # * :instance_name => How this object will appear in your views. In this case
25
- # the default is @project. Overwrite it with a symbol.
26
- #
27
- # belongs_to :project, :instance_name => :my_project
28
- #
29
- # * :finder => Specifies which method should be called to instantiate the
30
- # parent. Let's suppose you are using slugs ("this-is-project-title") in URLs
31
- # so your tasks url would be: "projects/this-is-project-title/tasks". Then you
32
- # should do this in your TasksController:
33
- #
34
- # belongs_to :project, :finder => :find_by_title!
35
- #
36
- # This will make your projects be instantiated as:
37
- #
38
- # Project.find_by_title!(params[:project_id])
39
- #
40
- # Instead of:
41
- #
42
- # Project.find(params[:project_id])
43
- #
44
- # * param => Allows you to specify params key used to instantiate the parent.
45
- # Default is :parent_id, which in this case is :project_id.
46
- #
47
- # * route_name => Allows you to specify what is the route name in your url
48
- # helper. By default is 'project'. But if your url helper should be
49
- # "admin_project_task_url" instead of "project_task_url", just do:
50
- #
51
- # belongs_to :project, :route_name => "admin_project"
52
- #
53
- # = nested_belongs_to
54
- #
55
- # If for some reason you need to nested more than two resources, you can do:
56
- #
57
- # class TasksController
58
- # belongs_to :company, :project
59
- # end
60
- #
61
- # ATTENTION! This DOES NOT mean polymorphic associations as in resource_controller.
62
- # Polymorphic associations are not supported yet.
63
- #
64
- # It means that companies have many projects which have many tasks. You URL
65
- # should be:
66
- #
67
- # /companies/:company_id/projects/:project_id/tasks/:id
68
- #
69
- # Everything will be handled for you again. And all defaults will describe above
70
- # will be assumed. But if you have to change the defaults. You will have to
71
- # specify one association by one:
72
- #
73
- # class TasksController
74
- # belongs_to :company, :finder => :find_by_name!, :param => :company_name
75
- # belongs_to :project
76
- # end
77
- #
78
- # belongs_to is aliased as nested_belongs_to, so this provides a nicer syntax:
79
- #
80
- # class TasksController
81
- # nested_belongs_to :company, :finder => :find_by_name!, :param => :company_name
82
- # nested_belongs_to :project
83
- # end
84
- #
85
- # In this case the association chain would be:
86
- #
87
- # Company.find_by_name!(params[:company_name]).projects.find(params[:project_id]).tasks.find(:all)
88
- #
89
- # When you are using nested resources, you have one more option to config.
90
- # Let's suppose that to get all projects from a company, you have to do:
91
- #
92
- # Company.admin_projects
93
- #
94
- # Instead of:
95
- #
96
- # Company.projects
97
- #
98
- # In this case, you can set the collection_name in belongs_to:
99
- #
100
- # nested_belongs_to :project, :collection_name => 'admin_projects'
101
- #
102
- # = polymorphic associations
103
- #
104
- # In some cases you have a resource that belongs to two different resources
105
- # but not at the same time. For example, let's suppose you have File, Message
106
- # and Task as resources and they are all commentable.
107
- #
108
- # Polymorphic associations allows you to create just one controller that will
109
- # deal with each case.
110
- #
111
- # class Comment < InheritedResources::Base
112
- # belongs_to :file, :message, :task, :polymorphic => true
113
- # end
114
- #
115
- # Your routes should be something like:
116
- #
117
- # m.resources :files, :has_many => :comments #=> /files/13/comments
118
- # m.resources :tasks, :has_many => :comments #=> /tasks/17/comments
119
- # m.resources :messages, :has_many => :comments #=> /messages/11/comments
120
- #
121
- # When using polymorphic associations, you get some free helpers:
122
- #
123
- # parent? #=> true
124
- # parent_type #=> :task
125
- # parent_class #=> Task
126
- # parent #=> @task
127
- #
128
- # This polymorphic controllers thing is a great idea by James Golick and he
129
- # built it in resource_controller. Here is just a re-implementation.
130
- #
131
- # = nested polymorphic associations
132
- #
133
- # You can have polymorphic associations with nested resources. Let's suppose
134
- # that our File, Task and Message resources in the previous example belongs to
135
- # a project.
136
- #
137
- # This way we can have:
138
- #
139
- # class Comment < InheritedResources::Base
140
- # belongs_to :project {
141
- # belongs_to :file, :message, :task, :polymorphic => true
142
- # }
143
- # end
144
- #
145
- # Or:
146
- #
147
- # class Comment < InheritedResources::Base
148
- # nested_belongs_to :project
149
- # nested_belongs_to :file, :message, :task, :polymorphic => true
150
- # end
151
- #
152
- # Choose the syntax that makes more sense to you. :)
153
- #
154
- # Finally your routes should be something like:
155
- #
156
- # map.resources :projects do |m|
157
- # m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments
158
- # m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments
159
- # m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments
160
- # end
161
- #
162
- # The helpers work in the same way as above.
163
- #
164
- # = singleton
165
- #
166
- # If you have singleton resources, in other words, if your controller resource
167
- # associates to another through a has_one association, you can pass the option
168
- # :singleton to it. It will deal with all the details and automacally remove
169
- # the :index action.
170
- #
171
- # class ManagersController < InheritedResources::Base
172
- # belongs_to :project, :singleton => true # a project has one manager
173
- # end
174
- #
175
- module InheritedResources #:nodoc:
176
- module BelongsTo #:nodoc:
177
-
178
- protected
179
- def belongs_to(*symbols, &block)
180
- options = symbols.extract_options!
181
-
182
- options.symbolize_keys!
183
- options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param, :finder, :route_name, :collection_name, :singleton, :polymorphic)
184
-
185
- acts_as_singleton! if singleton = options.delete(:singleton)
186
- acts_as_polymorphic! if polymorphic = options.delete(:polymorphic)
187
-
188
- raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
189
- raise ArgumentError, 'You cannot define multiple associations with the options: #{options.keys.inspect}.' unless symbols.size == 1 || options.empty?
190
-
191
- # Add BelongsToHelpers if we haven't yet.
192
- include BelongsToHelpers if self.parents_symbols.empty?
193
-
194
- # Set configuration default values
195
- symbols.each do |symbol|
196
- symbol = symbol.to_sym
197
-
198
- if polymorphic
199
- self.parents_symbols << :polymorphic unless self.parents_symbols.include? :polymorphic
200
- self.polymorphic_symbols << symbol
201
- else
202
- self.parents_symbols << symbol
203
- end
204
-
205
- config = self.resources_configuration[symbol] = {}
206
- config[:parent_class] = options.delete(:parent_class)
207
- config[:parent_class] ||= (options.delete(:class_name) || symbol).to_s.classify.constantize rescue nil
208
- config[:collection_name] = (options.delete(:collection_name) || symbol.to_s.pluralize).to_sym
209
- config[:instance_name] = (options.delete(:instance_name) || symbol).to_sym
210
- config[:param] = (options.delete(:param) || "#{symbol}_id").to_sym
211
- config[:finder] = (options.delete(:finder) || :find).to_sym
212
- config[:route_name] = (options.delete(:route_name) || symbol).to_s
213
- config[:polymorphic] = polymorphic
214
- end
215
-
216
- # Regenerate url helpers unless block is given
217
- if block_given?
218
- class_eval(&block)
219
- else
220
- InheritedResources::UrlHelpers.create_resources_url_helpers!(self)
221
- end
222
- end
223
- alias :nested_belongs_to :belongs_to
224
-
225
- end
226
- end
227
-