josevalim-inherited_resources 0.7.1 → 0.7.2
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.
- data/CHANGELOG +8 -0
- data/README +21 -9
- data/lib/inherited_resources/base.rb +12 -10
- data/lib/inherited_resources/base_helpers.rb +53 -9
- data/lib/inherited_resources/has_scope_helpers.rb +1 -0
- data/test/has_scope_test.rb +11 -1
- data/test/redirect_to_test.rb +64 -8
- metadata +2 -2
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.
|
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,
|
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
|
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!
|
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
|
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
|
-
|
284
|
-
|
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
|
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(
|
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,
|
79
|
-
format.html { redirect_to(
|
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,
|
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(
|
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(
|
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(
|
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,
|
123
|
-
format.html { redirect_to(
|
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
|
-
#
|
86
|
-
#
|
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 =>
|
225
|
-
}.merge(
|
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
|
data/test/has_scope_test.rb
CHANGED
@@ -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={})
|
data/test/redirect_to_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class SuperMachine;
|
4
4
|
def self.human_name; 'Machine'; end
|
5
5
|
end
|
6
6
|
|
7
|
-
|
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
|
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
|
-
|
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.
|
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-
|
12
|
+
date: 2009-04-28 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|