josevalim-inherited_resources 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,13 @@
1
1
  # Version 0.7
2
2
 
3
+ * Allow procs as default value in has scope to be able to use values from session, for example.
4
+ * Allow blocks with arity 0 or -1 to be given as the redirect url:
5
+
6
+ def destroy
7
+ destroy!{ project_url(@project) }
8
+ end
9
+
10
+ * Allow interpolation_options to be set in the application controller.
3
11
  * Added has_scope to controller (an interface for named_scopes).
4
12
  * Added polymorphic_belongs_to, optional_belongs_to and singleton_belongs_to
5
13
  as quick methods.
data/README CHANGED
@@ -1,6 +1,6 @@
1
1
  Inherited Resources
2
2
  License: MIT
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
 
5
5
  You can also read this README in pretty html at the GitHub project Wiki page:
6
6
 
@@ -18,7 +18,7 @@ code by following fat models and skinny controllers convention.
18
18
 
19
19
  Inherited Resources is tested and compatible with Rails 2.2.x and Rails 2.3.x.
20
20
 
21
- keywords: resources, controller, singleton, belongs_to, polymorphic and I18n
21
+ keywords: resources, controller, singleton, belongs_to, polymorphic, named_scope and I18n
22
22
 
23
23
  Installation
24
24
  ------------
@@ -135,7 +135,7 @@ and scopes (more about this below).
135
135
 
136
136
  InheritedResources also introduces another method called begin_of_association_chain.
137
137
  It's mostly used when you want to create resources based on the @current_user and
138
- you have urls like "account/projects". In such cases, so you have to do
138
+ you have urls like "account/projects". In such cases, you have to do
139
139
  @current_user.projects.find or @current_user.projects.build in your actions.
140
140
 
141
141
  You can deal with it just doing:
@@ -175,13 +175,13 @@ That's why all methods have aliases. So this is equivalent:
175
175
  end
176
176
  end
177
177
 
178
- Even more, since most of the times when you change a :create, :update or :destroy
178
+ Even more, since most of the times when you change a create, update or destroy
179
179
  action is because you want to to change to where it redirects, a shortcut is
180
180
  provided. So you can do:
181
181
 
182
182
  class ProjectsController < InheritedResources::Base
183
183
  def destroy
184
- destroy!(root_url)
184
+ destroy!{ root_url }
185
185
  end
186
186
  end
187
187
 
@@ -225,7 +225,7 @@ Looks to verbose, right? We can actually do:
225
225
  end
226
226
  end
227
227
 
228
- Much better! So explaning everything: when you give a block which expects one
228
+ Much better! So explaining everything: when you give a block which expects one
229
229
  argument it will be executed in both scenarios: success and failure. But If you
230
230
  give a block that expects two arguments, the first will be executed only in
231
231
  success scenarios and the second in failure scenarios. You keep everything
@@ -280,8 +280,15 @@ Then you will finally have:
280
280
 
281
281
  "Hooray! The project "Plataforma" was updated!"
282
282
 
283
- If your controller is namespaced, for example Admin::ProjectsController, the
284
- messages will be checked in the following order:
283
+ By default, resource name is capitalized. If you want to make it lower case, you
284
+ can add to your application controller:
285
+
286
+ def interpolation_options
287
+ { :resource_name => resource_class.human_name.downcase }
288
+ end
289
+
290
+ Finally, if your controller is namespaced, for example Admin::ProjectsController,
291
+ the messages will be checked in the following order:
285
292
 
286
293
  flash.admin.projects.create.notice
287
294
  flash.admin.actions.create.notice
@@ -302,7 +309,7 @@ it also is named_scope fluent. Let's suppose our Project model with the scopes:
302
309
 
303
310
  Your controller:
304
311
 
305
- class GraduationsController < InheritedResources::Base
312
+ class ProjectsController < InheritedResources::Base
306
313
  has_scope :featured, :boolean => true, :only => :index
307
314
  has_scope :by_methodology
308
315
  has_scope :limit, :default => 10
@@ -324,6 +331,11 @@ In the last case, it would return:
324
331
 
325
332
  { :featured => "true", :by_methodology => "agile", :limit => "20" }
326
333
 
334
+ Finally, let's suppose you store on the session how many projects the user sees
335
+ per page. In such cases, you can give a proc as default value:
336
+
337
+ has_scope :limit, :default => proc{|c| c.session[:limit] || 10 }
338
+
327
339
  Belongs to
328
340
  ----------
329
341
 
@@ -67,23 +67,23 @@ module InheritedResources
67
67
  alias :edit! :edit
68
68
 
69
69
  # POST /resources
70
- def create(redirect_to=nil, &block)
70
+ def create(redirect_url=nil, &block)
71
71
  object = build_resource(params[resource_instance_name])
72
+ respond_block, redirect_block = select_block_by_arity(block)
72
73
 
73
74
  if object.save
74
75
  set_flash_message!(:notice, '{{resource_name}} was successfully created.')
75
-
76
76
  options = { :with => object, :status => :created, :location => (resource_url rescue nil) }
77
77
 
78
- respond_to_with_dual_blocks(true, block, options) do |format|
79
- format.html { redirect_to(redirect_to || resource_url) }
78
+ respond_to_with_dual_blocks(true, respond_block, options) do |format|
79
+ format.html { redirect_to parse_redirect_url(redirect_url, :resource_url, redirect_block) }
80
80
  end
81
81
  else
82
82
  set_flash_message!(:error)
83
83
 
84
84
  options = { :with => object.errors, :status => :unprocessable_entity }
85
85
 
86
- respond_to_with_dual_blocks(false, block, options) do |format|
86
+ respond_to_with_dual_blocks(false, respond_block, options) do |format|
87
87
  format.html { render :action => 'new' }
88
88
  end
89
89
  end
@@ -91,14 +91,15 @@ module InheritedResources
91
91
  alias :create! :create
92
92
 
93
93
  # PUT /resources/1
94
- def update(redirect_to=nil, &block)
94
+ def update(redirect_url=nil, &block)
95
95
  object = resource
96
+ respond_block, redirect_block = select_block_by_arity(block)
96
97
 
97
98
  if object.update_attributes(params[resource_instance_name])
98
99
  set_flash_message!(:notice, '{{resource_name}} was successfully updated.')
99
100
 
100
101
  respond_to_with_dual_blocks(true, block) do |format|
101
- format.html { redirect_to(redirect_to || resource_url) }
102
+ format.html { redirect_to parse_redirect_url(redirect_url, :resource_url, redirect_block) }
102
103
  format.all { head :ok }
103
104
  end
104
105
  else
@@ -114,13 +115,14 @@ module InheritedResources
114
115
  alias :update! :update
115
116
 
116
117
  # DELETE /resources/1
117
- def destroy(redirect_to=nil, &block)
118
+ def destroy(redirect_url=nil, &block)
118
119
  resource.destroy
120
+ respond_block, redirect_block = select_block_by_arity(block)
119
121
 
120
122
  set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.')
121
123
 
122
- respond_to_with_dual_blocks(nil, block) do |format|
123
- format.html { redirect_to(redirect_to || collection_url) }
124
+ respond_to_with_dual_blocks(nil, respond_block) do |format|
125
+ format.html { redirect_to parse_redirect_url(redirect_url, :collection_url, redirect_block) }
124
126
  format.all { head :ok }
125
127
  end
126
128
  end
@@ -82,12 +82,9 @@ module InheritedResources
82
82
  # Overwrite this method to provide other interpolation options when
83
83
  # the flash message is going to be set.
84
84
  #
85
- # You cannot overwrite :resource_name and :default options using this
86
- # method. Check <tt>set_flash_message!</tt> for more information.
87
- #
88
- def interpolation_options
89
- { }
90
- end
85
+ # def interpolation_options
86
+ # { }
87
+ # end
91
88
 
92
89
  private
93
90
 
@@ -216,13 +213,29 @@ module InheritedResources
216
213
  # flash.cars.create.status
217
214
  # flash.actions.create.status
218
215
  #
219
- def set_flash_message!(status, default_message = '')
216
+ def set_flash_message!(status, default_message=nil)
220
217
  return flash[status] = default_message unless defined?(::I18n)
221
218
 
219
+ resource_name = if resource_class
220
+ if resource_class.respond_to?(:human_name)
221
+ resource_class.human_name
222
+ else
223
+ resource_class.name.humanize
224
+ end
225
+ else
226
+ "Resource"
227
+ end
228
+
229
+ given_options = if self.respond_to?(:interpolation_options)
230
+ interpolation_options
231
+ else
232
+ {}
233
+ end
234
+
222
235
  options = {
223
236
  :default => default_message || '',
224
- :resource_name => resource_class ? resource_class.human_name : 'Resource',
225
- }.merge(interpolation_options)
237
+ :resource_name => resource_name
238
+ }.merge(given_options)
226
239
 
227
240
  defaults = []
228
241
  slices = controller_path.split('/')
@@ -284,5 +297,36 @@ module InheritedResources
284
297
  []
285
298
  end
286
299
 
300
+ # If block is not nil, call it and uses the result as redirect to url.
301
+ # Otherwise, send the default url as message.
302
+ #
303
+ def parse_redirect_url(redirect_url, default_url, block) #:nodoc:
304
+ if redirect_url
305
+ ActiveSupport::Deprecation.warn "#{action_name}!(redirect_url) is deprecated. " <<
306
+ "Use #{action_name}!{ redirect_url } instead."
307
+ return redirect_url
308
+ end
309
+
310
+ block ? block.call : send(default_url)
311
+ end
312
+
313
+ # Holds InheritedResources block structure. It returns two blocks: the first
314
+ # is used in respond_to blocks and the second is the redirect_to url.
315
+ #
316
+ def select_block_by_arity(block) #:nodoc
317
+ if block
318
+ case block.arity
319
+ when 2, 1
320
+ [block, nil]
321
+ when 0, -1
322
+ [nil, block]
323
+ else
324
+ raise ScriptError, "InheritedResources does not know how to handle blocks with arity #{block.arity}"
325
+ end
326
+ else
327
+ [nil, nil]
328
+ end
329
+ end
330
+
287
331
  end
288
332
  end
@@ -23,6 +23,7 @@ module InheritedResources
23
23
  value, call_scope = params[key], true
24
24
  elsif options.key?(:default)
25
25
  value, call_scope = options[:default], true
26
+ value = value.call(self) if value.is_a?(Proc)
26
27
  end
27
28
 
28
29
  if call_scope
@@ -7,8 +7,9 @@ end
7
7
  class TreesController < InheritedResources::Base
8
8
  has_scope :color
9
9
  has_scope :only_tall, :boolean => true, :only => :index
10
- has_scope :shadown_range, :default => 10, :except => [ :index, :show, :destroy ]
10
+ has_scope :shadown_range, :default => 10, :except => [ :index, :show, :destroy, :new ]
11
11
  has_scope :root_type, :key => :root
12
+ has_scope :calculate_height, :default => proc {|c| c.session[:height] || 20 }, :only => :new
12
13
  end
13
14
 
14
15
  class HasScopeTest < ActionController::TestCase
@@ -92,6 +93,15 @@ class HasScopeTest < ActionController::TestCase
92
93
  assert_equal({ :root => 'outside' }, assigns(:current_scopes))
93
94
  end
94
95
 
96
+ def test_scope_with_default_value_as_proc
97
+ session[:height] = 100
98
+ Tree.expects(:calculate_height).with(100).returns(Tree).in_sequence
99
+ Tree.expects(:new).returns(mock_tree).in_sequence
100
+ get :new
101
+ assert_equal(mock_tree, assigns(:tree))
102
+ assert_equal({ :calculate_height => 100 }, assigns(:current_scopes))
103
+ end
104
+
95
105
  protected
96
106
 
97
107
  def mock_tree(stubs={})
@@ -1,11 +1,11 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
- class Machine;
3
+ class SuperMachine;
4
4
  def self.human_name; 'Machine'; end
5
5
  end
6
6
 
7
- class MachinesController < InheritedResources::Base
8
-
7
+ # Use this to test blocks with multiple arity in the future.
8
+ class SuperMachinesController < InheritedResources::Base
9
9
  def create
10
10
  create!('http://test.host/')
11
11
  end
@@ -17,31 +17,87 @@ class MachinesController < InheritedResources::Base
17
17
  def destroy
18
18
  destroy!('http://test.host/')
19
19
  end
20
+ end
21
+
22
+ class RedirectToWithArgumentTest < ActionController::TestCase
23
+ tests SuperMachinesController
24
+
25
+ def test_redirect_to_the_given_url_on_create
26
+ ActiveSupport::Deprecation.expects(:warn).with('create!(redirect_url) is deprecated. Use create!{ redirect_url } instead.')
27
+ SuperMachine.stubs(:new).returns(mock_machine(:save => true))
28
+ @controller.expects(:resource_url).times(0)
29
+ post :create
30
+ assert_redirected_to 'http://test.host/'
31
+ end
32
+
33
+ def test_redirect_to_the_given_url_on_update
34
+ ActiveSupport::Deprecation.expects(:warn).with('update!(redirect_url) is deprecated. Use update!{ redirect_url } instead.')
35
+ SuperMachine.stubs(:find).returns(mock_machine(:update_attributes => true))
36
+ @controller.expects(:resource_url).times(0)
37
+ put :update
38
+ assert_redirected_to 'http://test.host/'
39
+ end
40
+
41
+ def test_redirect_to_the_given_url_on_destroy
42
+ ActiveSupport::Deprecation.expects(:warn).with('destroy!(redirect_url) is deprecated. Use destroy!{ redirect_url } instead.')
43
+ SuperMachine.stubs(:find).returns(mock_machine(:destroy => true))
44
+ @controller.expects(:collection_url).times(0)
45
+ delete :destroy
46
+ assert_redirected_to 'http://test.host/'
47
+ end
48
+
49
+ protected
50
+ def mock_machine(stubs={})
51
+ @mock_machine ||= mock(stubs)
52
+ end
53
+ end
54
+
55
+ class Machine;
56
+ def self.human_name; 'Machine'; end
57
+ end
58
+
59
+ class MachinesController < InheritedResources::Base
60
+
61
+ def create
62
+ create!{ complex_url(:create, true, true) }
63
+ end
64
+
65
+ def update
66
+ update!{ complex_url(:update, false, false) }
67
+ end
68
+
69
+ def destroy
70
+ destroy!{ complex_url(:destroy, true, false) }
71
+ end
20
72
 
73
+ protected
74
+ def complex_url(name, arg2, arg3)
75
+ 'http://test.host/' + name.to_s
76
+ end
21
77
  end
22
78
 
23
- class RedirectToTest < ActionController::TestCase
79
+ class RedirectToWithBlockTest < ActionController::TestCase
24
80
  tests MachinesController
25
81
 
26
82
  def test_redirect_to_the_given_url_on_create
27
83
  Machine.stubs(:new).returns(mock_machine(:save => true))
28
84
  @controller.expects(:resource_url).times(0)
29
85
  post :create
30
- assert_redirected_to 'http://test.host/'
86
+ assert_redirected_to 'http://test.host/create'
31
87
  end
32
88
 
33
89
  def test_redirect_to_the_given_url_on_update
34
90
  Machine.stubs(:find).returns(mock_machine(:update_attributes => true))
35
91
  @controller.expects(:resource_url).times(0)
36
92
  put :update
37
- assert_redirected_to 'http://test.host/'
93
+ assert_redirected_to 'http://test.host/update'
38
94
  end
39
95
 
40
96
  def test_redirect_to_the_given_url_on_destroy
41
97
  Machine.stubs(:find).returns(mock_machine(:destroy => true))
42
98
  @controller.expects(:collection_url).times(0)
43
- put :destroy
44
- assert_redirected_to 'http://test.host/'
99
+ delete :destroy
100
+ assert_redirected_to 'http://test.host/destroy'
45
101
  end
46
102
 
47
103
  protected
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.7.1
4
+ version: 0.7.2
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-04-26 00:00:00 -07:00
12
+ date: 2009-04-28 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15