responder_controller 0.2.0 → 0.3.0
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 +6 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/responder_controller.rb +4 -297
- data/lib/responder_controller/actions.rb +57 -0
- data/lib/responder_controller/class_methods.rb +126 -0
- data/lib/responder_controller/instance_methods.rb +118 -0
- data/responder_controller.gemspec +14 -5
- data/spec/responder_controller/actions_spec.rb +140 -0
- data/spec/responder_controller/class_methods_spec.rb +266 -0
- data/spec/responder_controller/instance_methods_spec.rb +239 -0
- data/spec/responder_controller_spec.rb +2 -586
- metadata +13 -4
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
3
|
+
module ResponderController
|
4
|
+
# Instance methods that support the Actions module.
|
5
|
+
module InstanceMethods
|
6
|
+
delegate :model_class_name, :model_class, :scopes, :responds_within, :serves_scopes,
|
7
|
+
:to => "self.class"
|
8
|
+
|
9
|
+
# Apply scopes to the given query.
|
10
|
+
#
|
11
|
+
# Applicable scopes come from two places. They are either declared at the class level with
|
12
|
+
# <tt>ClassMethods#scope</tt>, or named in the request itself. The former is good for
|
13
|
+
# defining topics or enforcing security, while the latter is free slicing and dicing for
|
14
|
+
# clients.
|
15
|
+
#
|
16
|
+
# Class-level scopes are applied first. Request scopes come after, and are discovered by
|
17
|
+
# examining +params+. If any +params+ key matches a name found in
|
18
|
+
# <tt>ClassMethods#model_class.scopes.keys</tt>, then it is taken to be a scope and is
|
19
|
+
# applied. The values under that +params+ key are passed along as arguments.
|
20
|
+
def scope(query)
|
21
|
+
query = (scopes || []).inject(query) do |query, scope|
|
22
|
+
if Symbol === scope and model_class.scopes.key? scope
|
23
|
+
query.send scope
|
24
|
+
elsif Proc === scope
|
25
|
+
instance_exec query, &scope
|
26
|
+
else
|
27
|
+
raise ArgumentError.new "Unknown scope #{model_class}.#{scope}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
requested = (model_class.scopes.keys & params.keys.collect { |k| k.to_sym })
|
32
|
+
raise ForbiddenScope if serves_scopes[:only] && (requested - serves_scopes[:only]).any?
|
33
|
+
raise ForbiddenScope if serves_scopes[:except] && (requested & serves_scopes[:except]).any?
|
34
|
+
|
35
|
+
query = requested.inject(query) do |query, scope|
|
36
|
+
query.send scope, *params[scope.to_s] rescue raise BadScope
|
37
|
+
end
|
38
|
+
|
39
|
+
query
|
40
|
+
end
|
41
|
+
|
42
|
+
# Find all models in #scope.
|
43
|
+
#
|
44
|
+
# The initial query is <tt>ClassMethods#model_class.scoped</tt>.
|
45
|
+
def find_models
|
46
|
+
scope model_class.scoped
|
47
|
+
end
|
48
|
+
|
49
|
+
# Find a particular model.
|
50
|
+
#
|
51
|
+
# #find_models is asked to find a model with <tt>params[:id]</tt>. This ensures that
|
52
|
+
# class-level scopes are enforced (potentially for security.)
|
53
|
+
def find_model
|
54
|
+
find_models.find(params[:id])
|
55
|
+
end
|
56
|
+
|
57
|
+
# The underscored model class name, as a symbol.
|
58
|
+
#
|
59
|
+
# Model modules are omitted.
|
60
|
+
def model_slug
|
61
|
+
model_class_name.split('/').last.to_sym
|
62
|
+
end
|
63
|
+
|
64
|
+
# Like #model_slug, but plural.
|
65
|
+
def models_slug
|
66
|
+
model_slug.to_s.pluralize.to_sym
|
67
|
+
end
|
68
|
+
|
69
|
+
# The name of the instance variable holding a single model instance.
|
70
|
+
def model_ivar
|
71
|
+
"@#{model_slug}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# The name of the instance variable holding a collection of models.
|
75
|
+
def models_ivar
|
76
|
+
model_ivar.pluralize
|
77
|
+
end
|
78
|
+
|
79
|
+
# Retrive #models_ivar
|
80
|
+
def models
|
81
|
+
instance_variable_get models_ivar
|
82
|
+
end
|
83
|
+
|
84
|
+
# Assign #models_ivar
|
85
|
+
def models=(models)
|
86
|
+
instance_variable_set models_ivar, models
|
87
|
+
end
|
88
|
+
|
89
|
+
# Retrive #model_ivar
|
90
|
+
def model
|
91
|
+
instance_variable_get model_ivar
|
92
|
+
end
|
93
|
+
|
94
|
+
# Assign #model_ivar
|
95
|
+
def model=(model)
|
96
|
+
instance_variable_set model_ivar, model
|
97
|
+
end
|
98
|
+
|
99
|
+
# Apply ClassMethods#responds_within to the given model (or symbol.)
|
100
|
+
#
|
101
|
+
# "Apply" just means turning +responds_within+ into an array and appending +model+ to the
|
102
|
+
# end. If +responds_within+ is an array, it used directly.
|
103
|
+
#
|
104
|
+
# If it is a proc, it is called with +instance_exec+, passing +model+ in. It should return an
|
105
|
+
# array, which +model+ will be appended to. (So, don't include it in the return value.)
|
106
|
+
def responder_context(model)
|
107
|
+
context = responds_within.collect do |o|
|
108
|
+
o = instance_exec model, &o if o.is_a? Proc
|
109
|
+
o
|
110
|
+
end.flatten + [model]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Pass +model+ through InstanceMethods#responder_context, and pass that to #respond_with.
|
114
|
+
def respond_with_contextual(model)
|
115
|
+
respond_with *responder_context(model)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{responder_controller}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Phil Smith"]
|
@@ -25,7 +25,13 @@ Gem::Specification.new do |s|
|
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
27
|
"lib/responder_controller.rb",
|
28
|
+
"lib/responder_controller/actions.rb",
|
29
|
+
"lib/responder_controller/class_methods.rb",
|
30
|
+
"lib/responder_controller/instance_methods.rb",
|
28
31
|
"responder_controller.gemspec",
|
32
|
+
"spec/responder_controller/actions_spec.rb",
|
33
|
+
"spec/responder_controller/class_methods_spec.rb",
|
34
|
+
"spec/responder_controller/instance_methods_spec.rb",
|
29
35
|
"spec/responder_controller_spec.rb",
|
30
36
|
"spec/spec.opts",
|
31
37
|
"spec/spec_helper.rb"
|
@@ -36,7 +42,10 @@ Gem::Specification.new do |s|
|
|
36
42
|
s.rubygems_version = %q{1.3.6}
|
37
43
|
s.summary = %q{like resources_controller, but for rails 3 responders}
|
38
44
|
s.test_files = [
|
39
|
-
"spec/
|
45
|
+
"spec/responder_controller/actions_spec.rb",
|
46
|
+
"spec/responder_controller/class_methods_spec.rb",
|
47
|
+
"spec/responder_controller/instance_methods_spec.rb",
|
48
|
+
"spec/responder_controller_spec.rb",
|
40
49
|
"spec/spec_helper.rb"
|
41
50
|
]
|
42
51
|
|
@@ -45,14 +54,14 @@ Gem::Specification.new do |s|
|
|
45
54
|
s.specification_version = 3
|
46
55
|
|
47
56
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
-
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0.
|
57
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
|
49
58
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
50
59
|
else
|
51
|
-
s.add_dependency(%q<activesupport>, [">= 3.0.0.
|
60
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
|
52
61
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
53
62
|
end
|
54
63
|
else
|
55
|
-
s.add_dependency(%q<activesupport>, [">= 3.0.0.
|
64
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.0.beta3"])
|
56
65
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
57
66
|
end
|
58
67
|
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ResponderController do
|
4
|
+
|
5
|
+
class ApplicationController
|
6
|
+
include ResponderController
|
7
|
+
|
8
|
+
def params
|
9
|
+
@params ||= { :user_id => 'me', :id => 7 }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class PostsController < ApplicationController
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ResponderController::Actions do
|
17
|
+
before :each do
|
18
|
+
@controller = PostsController.new
|
19
|
+
@controller.stub!(:find_models).and_return(@posts = mock("some posts"))
|
20
|
+
@controller.stub!(:find_model).and_return(@post = mock("a post"))
|
21
|
+
@controller.stub!(:respond_with)
|
22
|
+
|
23
|
+
@posts.stub!(:build).and_return(@post)
|
24
|
+
@posts.stub!(:to_a).and_return([])
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#index' do
|
28
|
+
it 'assigns #find_models to #models=' do
|
29
|
+
@controller.should_receive(:find_models).and_return(@posts)
|
30
|
+
@controller.index
|
31
|
+
@controller.instance_variable_get('@posts').should == @posts
|
32
|
+
end
|
33
|
+
|
34
|
+
it '#respond_with_contextual @models.to_a' do
|
35
|
+
@posts.should_receive(:to_a).and_return(:posts_array)
|
36
|
+
@controller.should_receive(:respond_with_contextual).with(:posts_array)
|
37
|
+
@controller.index
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
[:show, :edit].each do |verb|
|
42
|
+
describe "##{verb}" do
|
43
|
+
it 'assigns #find_model to #model=' do
|
44
|
+
@controller.should_receive(:find_model).and_return(@post)
|
45
|
+
@controller.send verb
|
46
|
+
@controller.instance_variable_get('@post').should == @post
|
47
|
+
end
|
48
|
+
|
49
|
+
it '#respond_with_contextual @model' do
|
50
|
+
@controller.should_receive(:respond_with_contextual).with(@post)
|
51
|
+
@controller.send verb
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#new' do
|
57
|
+
it 'assigns #find_models.new to #model=' do
|
58
|
+
@posts.should_receive(:build).and_return(@post)
|
59
|
+
@controller.new
|
60
|
+
@controller.instance_variable_get('@post').should == @post
|
61
|
+
end
|
62
|
+
|
63
|
+
it '#respond_with_contextual @model' do
|
64
|
+
@controller.should_receive(:respond_with_contextual).with(@post)
|
65
|
+
@controller.new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#create' do
|
70
|
+
before :each do
|
71
|
+
@post.stub!(:save)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'passes params[model_slug] to #find_models.new' do
|
75
|
+
@controller.params[:post] = :params_to_new
|
76
|
+
@posts.should_receive(:build).with(:params_to_new)
|
77
|
+
@controller.create
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'assigns #find_models.new to #model=' do
|
81
|
+
@controller.create
|
82
|
+
@controller.instance_variable_get('@post').should == @post
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'saves the model' do
|
86
|
+
@post.should_receive(:save)
|
87
|
+
@controller.create
|
88
|
+
end
|
89
|
+
|
90
|
+
it '#respond_with_contextual @model' do
|
91
|
+
@controller.should_receive(:respond_with_contextual).with(@post)
|
92
|
+
@controller.create
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#update' do
|
97
|
+
before :each do
|
98
|
+
@post.stub!(:update_attributes)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'assigns #find_model to #model=' do
|
102
|
+
@controller.should_receive(:find_model).and_return(@post)
|
103
|
+
@controller.update
|
104
|
+
@controller.instance_variable_get('@post').should == @post
|
105
|
+
end
|
106
|
+
|
107
|
+
it "updates the model's attributes" do
|
108
|
+
@controller.params[:post] = :params_to_update
|
109
|
+
@post.should_receive(:update_attributes).with(:params_to_update)
|
110
|
+
@controller.update
|
111
|
+
end
|
112
|
+
|
113
|
+
it '#respond_with_contextual @model' do
|
114
|
+
@controller.should_receive(:respond_with_contextual).with(@post)
|
115
|
+
@controller.update
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#destroy' do
|
120
|
+
before :each do
|
121
|
+
@post.stub!(:destroy)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'finds the model' do
|
125
|
+
@controller.should_receive(:find_model).and_return(@post)
|
126
|
+
@controller.destroy
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'destroys the model' do
|
130
|
+
@post.should_receive(:destroy)
|
131
|
+
@controller.destroy
|
132
|
+
end
|
133
|
+
|
134
|
+
it '#respond_with_contextual #models_slug' do
|
135
|
+
@controller.should_receive(:respond_with_contextual).with(:posts)
|
136
|
+
@controller.destroy
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Post
|
4
|
+
class <<self
|
5
|
+
def scopes
|
6
|
+
{
|
7
|
+
:recent => "a scope",
|
8
|
+
:unpublished => "another",
|
9
|
+
:authored_by => "and another",
|
10
|
+
:commented_on_by => "even one more",
|
11
|
+
:published_after => "man they just keep coming"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Accounts
|
18
|
+
class User
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Admin
|
23
|
+
class Setting
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ResponderController::ClassMethods do
|
28
|
+
|
29
|
+
class ApplicationController
|
30
|
+
include ResponderController
|
31
|
+
|
32
|
+
def params
|
33
|
+
@params ||= { :user_id => 'me', :id => 7 }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class PostsController < ApplicationController
|
38
|
+
end
|
39
|
+
|
40
|
+
class Admin::SettingsController < ApplicationController
|
41
|
+
end
|
42
|
+
|
43
|
+
before :each do
|
44
|
+
@query = mock("the scoped query")
|
45
|
+
@query.stub!(:unpublished).and_return(@query)
|
46
|
+
@query.stub!(:recent).and_return(@query)
|
47
|
+
@query.stub!(:owned_by).with('me').and_return(@query)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '.model_class_name', 'by default' do
|
51
|
+
it 'is taken from the controller class name' do
|
52
|
+
PostsController.model_class_name.should == 'post'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "includes the controller's modules divided by whacks" do
|
56
|
+
Admin::SettingsController.model_class_name.should == 'admin/setting'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '.serves_model' do
|
61
|
+
it 'sets the model class name to the passed value' do
|
62
|
+
PostsController.serves_model 'some_other_model'
|
63
|
+
PostsController.model_class_name.should == 'some_other_model'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'accepts symbols as well as strings' do
|
67
|
+
PostsController.serves_model :some_other_model
|
68
|
+
PostsController.model_class_name.should == 'some_other_model'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'raises ArgumentError for other values' do
|
72
|
+
lambda do
|
73
|
+
PostsController.serves_model [:not_a, :string_or_symbol]
|
74
|
+
end.should raise_error ArgumentError
|
75
|
+
end
|
76
|
+
|
77
|
+
after :each do
|
78
|
+
PostsController.serves_model :post
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '.model_class' do
|
83
|
+
it 'is the constant named by model_class_name' do
|
84
|
+
PostsController.model_class.should == Post
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'handles modules in the name' do
|
88
|
+
Admin::SettingsController.model_class.should == Admin::Setting
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '.scope' do
|
93
|
+
it 'takes a string naming a scope on model_class' do
|
94
|
+
PostsController.scope 'unpublished'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can take a symbol' do
|
98
|
+
PostsController.scope :recent
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '.scopes' do
|
103
|
+
it 'is an array of scopes in order, as symbols' do
|
104
|
+
PostsController.scopes.should == [:unpublished, :recent]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '.scope', 'with a block' do
|
109
|
+
it 'omits the name and can reference params' do
|
110
|
+
PostsController.scope do |posts|
|
111
|
+
posts.owned_by(params[:user_id])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'puts a lambda on .scopes' do
|
116
|
+
PostsController.scopes.last.should be_a Proc
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '.scope', 'with something that is not a string, symbol or block' do
|
121
|
+
it 'explodes' do
|
122
|
+
lambda do
|
123
|
+
PostsController.scope [:not_a, :string_symbol_or_block]
|
124
|
+
end.should raise_error ArgumentError
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '.serves_scopes' do
|
129
|
+
before :each do
|
130
|
+
@controller = PostsController.new
|
131
|
+
@controller.params['commented_on_by'] = 'you'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'can specify a white list of active record scopes to serve' do
|
135
|
+
PostsController.serves_scopes :only => [:recent, :authored_by, :published_after]
|
136
|
+
lambda do
|
137
|
+
@controller.scope @query
|
138
|
+
end.should raise_error(ResponderController::ForbiddenScope)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'can specify just one scope to white list' do
|
142
|
+
PostsController.serves_scopes :only => :recent
|
143
|
+
lambda do
|
144
|
+
@controller.scope @query
|
145
|
+
end.should raise_error(ResponderController::ForbiddenScope)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'can specify a black list of active record scopes to deny' do
|
149
|
+
PostsController.serves_scopes :except => [:commented_on_by, :unpublished]
|
150
|
+
lambda do
|
151
|
+
@controller.scope @query
|
152
|
+
end.should raise_error(ResponderController::ForbiddenScope)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'can specify just one scope to black list' do
|
156
|
+
PostsController.serves_scopes :except => :commented_on_by
|
157
|
+
lambda do
|
158
|
+
@controller.scope @query
|
159
|
+
end.should raise_error(ResponderController::ForbiddenScope)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'whines if passed anything other than a hash' do
|
163
|
+
lambda do
|
164
|
+
PostsController.serves_scopes 'cupcakes!'
|
165
|
+
end.should raise_error TypeError
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'whines about keys other than :only and :except' do
|
169
|
+
lambda do
|
170
|
+
PostsController.serves_scopes 'only' => :recent
|
171
|
+
end.should raise_error ArgumentError
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'whines when both :only and :except are passed' do
|
175
|
+
lambda do
|
176
|
+
PostsController.serves_scopes :only => :recent, :except => :commented_on_by
|
177
|
+
end.should raise_error ArgumentError
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'whines if both :only and :except are passed between different calls' do
|
181
|
+
PostsController.serves_scopes :only => :recent
|
182
|
+
lambda do
|
183
|
+
PostsController.serves_scopes :except => :commented_on_by
|
184
|
+
end.should raise_error ArgumentError
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'accumulates scopes passed over multiple calls' do
|
188
|
+
PostsController.serves_scopes :only => :recent
|
189
|
+
PostsController.serves_scopes :only => :authored_by
|
190
|
+
PostsController.serves_scopes[:only].should == [:recent, :authored_by]
|
191
|
+
end
|
192
|
+
|
193
|
+
after :each do
|
194
|
+
PostsController.serves_scopes.clear # clean up
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe '.responds_within' do
|
199
|
+
it "contains the model's enclosing module names as symbols by default" do
|
200
|
+
PostsController.responds_within.should == []
|
201
|
+
Admin::SettingsController.responds_within.should == [:admin]
|
202
|
+
end
|
203
|
+
|
204
|
+
it "takes, saves and returns a varargs" do
|
205
|
+
PostsController.responds_within(:foo, :bar, :baz).should == [:foo, :bar, :baz]
|
206
|
+
PostsController.responds_within.should == [:foo, :bar, :baz]
|
207
|
+
end
|
208
|
+
|
209
|
+
it "accumulates between calls" do
|
210
|
+
PostsController.responds_within(:foo).should == [:foo]
|
211
|
+
PostsController.responds_within(:bar, :baz).should == [:foo, :bar, :baz]
|
212
|
+
PostsController.responds_within.should == [:foo, :bar, :baz]
|
213
|
+
end
|
214
|
+
|
215
|
+
it "can take a block instead" do
|
216
|
+
block = lambda {}
|
217
|
+
PostsController.responds_within(&block).should == [block]
|
218
|
+
PostsController.responds_within.should == [block]
|
219
|
+
end
|
220
|
+
|
221
|
+
it "whines if both positional arguments and a block are passed" do
|
222
|
+
lambda do
|
223
|
+
PostsController.responds_within(:foo, :bar, :baz) {}
|
224
|
+
end.should raise_error ArgumentError
|
225
|
+
end
|
226
|
+
|
227
|
+
after :each do
|
228
|
+
PostsController.instance_variable_set "@responds_within", nil # clear out the garbage
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe '.children_of' do
|
233
|
+
it 'takes a underscored model class name' do
|
234
|
+
PostsController.children_of 'accounts/user'
|
235
|
+
end
|
236
|
+
|
237
|
+
it "can take symbols" do
|
238
|
+
PostsController.children_of 'accounts/user'.to_sym
|
239
|
+
end
|
240
|
+
|
241
|
+
it "creates a scope filtering by the parent model's foreign key as passed in params" do
|
242
|
+
PostsController.children_of 'accounts/user'
|
243
|
+
controller = PostsController.new
|
244
|
+
controller.params[:user_id] = :the_user_id
|
245
|
+
|
246
|
+
user_query = mock("user-restricted query")
|
247
|
+
@query.should_receive(:where).with(:user_id => :the_user_id).and_return(user_query)
|
248
|
+
controller.scope(@query).should == user_query
|
249
|
+
end
|
250
|
+
|
251
|
+
it "adds a responds_within context, of the parent modules followed by the parent itself" do
|
252
|
+
PostsController.children_of 'accounts/user'
|
253
|
+
controller = PostsController.new
|
254
|
+
controller.params[:user_id] = :the_user_id
|
255
|
+
|
256
|
+
Accounts::User.should_receive(:find).with(:the_user_id).and_return(user = mock("the user"))
|
257
|
+
|
258
|
+
controller.responder_context(:argument).should == [:accounts, user, :argument]
|
259
|
+
end
|
260
|
+
|
261
|
+
after :each do
|
262
|
+
PostsController.instance_variable_set "@responds_within", nil # clear out the garbage
|
263
|
+
PostsController.scopes.clear
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|