josevalim-inherited_resources 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
-