heimdallr-resource 1.0.3 → 1.2.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/.rspec +1 -2
- data/CHANGELOG.md +9 -0
- data/README.md +9 -5
- data/heimdallr-resource.gemspec +4 -3
- data/lib/heimdallr-resource.rb +2 -0
- data/lib/heimdallr/resource.rb +21 -191
- data/lib/heimdallr/resource_implementation.rb +190 -0
- data/spec/{resource_spec.rb → controllers/entities_controller_spec.rb} +25 -7
- data/spec/controllers/fluffies_controller_spec.rb +20 -0
- data/spec/controllers/things_controller_spec.rb +31 -0
- data/spec/dummy/app/controllers/{entity_controller.rb → entities_controller.rb} +6 -2
- data/spec/dummy/app/controllers/things_controller.rb +29 -0
- data/spec/dummy/app/models/entity.rb +2 -0
- data/spec/dummy/app/models/thing.rb +16 -0
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/routes.rb +6 -5
- data/spec/dummy/db/schema.rb +5 -0
- data/spec/models/resource_implementation_spec.rb +382 -0
- data/spec/models/resource_spec.rb +91 -0
- data/spec/spec_helper.rb +1 -0
- metadata +44 -48
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/config/environments/development.rb +0 -23
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -10
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/fluffies_spec.rb +0 -22
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe EntitiesController, :type => :controller do
|
4
4
|
before(:all) do
|
5
|
+
User.destroy_all
|
6
|
+
Entity.destroy_all
|
7
|
+
|
5
8
|
@john = User.create! :admin => false
|
6
9
|
@maria = User.create! :admin => false
|
7
10
|
@admin = User.create! :admin => true
|
11
|
+
|
8
12
|
@private = Entity.create! :name => 'ent1', :public => false
|
13
|
+
@private_own = Entity.create! :name => 'ent1', :public => false, :owner_id => @john.id
|
9
14
|
@public = Entity.create! :name => 'ent1', :public => true, :owner_id => @john.id
|
10
15
|
end
|
11
16
|
|
@@ -14,14 +19,27 @@ describe EntityController, :type => :controller do
|
|
14
19
|
User.mock @admin
|
15
20
|
get :index
|
16
21
|
|
17
|
-
assigns(:entities).
|
22
|
+
assigns(:entities).should have(3).items
|
18
23
|
end
|
19
24
|
|
20
25
|
it "hides non-public entities" do
|
21
26
|
User.mock @john
|
22
27
|
get :index
|
23
28
|
|
24
|
-
assigns(:entities).
|
29
|
+
assigns(:entities).should have(2).items
|
30
|
+
end
|
31
|
+
|
32
|
+
it "shows private to owner" do
|
33
|
+
User.mock @john
|
34
|
+
get :show, {:id => @private_own.id}
|
35
|
+
|
36
|
+
assigns(:entity).insecure.should == @private_own
|
37
|
+
end
|
38
|
+
|
39
|
+
it "hides private from non-owner" do
|
40
|
+
User.mock @maria
|
41
|
+
|
42
|
+
expect { get :show, {:id => @private_own.id} }.to raise_error
|
25
43
|
end
|
26
44
|
|
27
45
|
it "allows creation for admin" do
|
@@ -33,7 +51,7 @@ describe EntityController, :type => :controller do
|
|
33
51
|
|
34
52
|
it "disallows creation for non-admin" do
|
35
53
|
User.mock @john
|
36
|
-
expect { post :create, {} }.
|
54
|
+
expect { post :create, {} }.to raise_error
|
37
55
|
end
|
38
56
|
|
39
57
|
it "allows update for admin" do
|
@@ -46,7 +64,7 @@ describe EntityController, :type => :controller do
|
|
46
64
|
|
47
65
|
it "disallows update for non-admin" do
|
48
66
|
User.mock @john
|
49
|
-
expect { post :update, {:id => @public.id} }.
|
67
|
+
expect { post :update, {:id => @public.id} }.to raise_error
|
50
68
|
end
|
51
69
|
|
52
70
|
it "allows destroy for admin" do
|
@@ -67,7 +85,7 @@ describe EntityController, :type => :controller do
|
|
67
85
|
|
68
86
|
it "disallows destroy for nobody" do
|
69
87
|
User.mock @maria
|
70
|
-
expect { post :destroy, {:id => @public.id} }.
|
88
|
+
expect { post :destroy, {:id => @public.id} }.to raise_error
|
71
89
|
end
|
72
90
|
|
73
91
|
it "assigns the custom methods" do
|
@@ -78,4 +96,4 @@ describe EntityController, :type => :controller do
|
|
78
96
|
assigns(:entity).id.should == @public.id
|
79
97
|
end
|
80
98
|
end
|
81
|
-
end
|
99
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FluffiesController, :type => :controller do
|
4
|
+
before(:all) do
|
5
|
+
User.destroy_all
|
6
|
+
Entity.destroy_all
|
7
|
+
|
8
|
+
@admin = User.create! :admin => true
|
9
|
+
|
10
|
+
@entity1 = Entity.create! :name => 'entity 1'
|
11
|
+
@entity2 = Entity.create! :name => 'entity 2'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "loads entity resources and assigns to @entities" do
|
15
|
+
User.mock @admin
|
16
|
+
get :index
|
17
|
+
|
18
|
+
assigns(:entities).should have(2).items
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThingsController, :type => :controller do
|
4
|
+
before(:all) do
|
5
|
+
User.delete_all
|
6
|
+
Entity.delete_all
|
7
|
+
|
8
|
+
@admin = User.create! :admin => true
|
9
|
+
|
10
|
+
@entity1 = Entity.create! :name => 'entity 1'
|
11
|
+
@entity2 = Entity.create! :name => 'entity 2'
|
12
|
+
|
13
|
+
@thing1 = Thing.create! :name => 'thing 1', :entity_id => @entity1.id
|
14
|
+
@thing2 = Thing.create! :name => 'thing 2', :entity_id => @entity1.id
|
15
|
+
@thing3 = Thing.create! :name => 'thing 3', :entity_id => @entity2.id
|
16
|
+
end
|
17
|
+
|
18
|
+
it "loads entity resource and assigns to @entity" do
|
19
|
+
User.mock @admin
|
20
|
+
get :index, :entity_id => @entity1.id
|
21
|
+
|
22
|
+
assigns(:entity).id.should == @entity1.id
|
23
|
+
end
|
24
|
+
|
25
|
+
it "loads thing resources through @entity and assigns to @things" do
|
26
|
+
User.mock @admin
|
27
|
+
get :index, :entity_id => @entity1.id
|
28
|
+
|
29
|
+
assigns(:things).should have(2).items
|
30
|
+
end
|
31
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class EntitiesController < ApplicationController
|
2
2
|
include Heimdallr::Resource
|
3
3
|
|
4
4
|
load_and_authorize_resource
|
@@ -7,6 +7,10 @@ class EntityController < ApplicationController
|
|
7
7
|
render :nothing => true
|
8
8
|
end
|
9
9
|
|
10
|
+
def show
|
11
|
+
render :nothing => true
|
12
|
+
end
|
13
|
+
|
10
14
|
def new
|
11
15
|
render :nothing => true
|
12
16
|
end
|
@@ -30,4 +34,4 @@ class EntityController < ApplicationController
|
|
30
34
|
def penetrate
|
31
35
|
render :nothing => true
|
32
36
|
end
|
33
|
-
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ThingsController < ApplicationController
|
2
|
+
include Heimdallr::Resource
|
3
|
+
|
4
|
+
load_and_authorize_resource :through => :entity
|
5
|
+
|
6
|
+
def index
|
7
|
+
render :nothing => true
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
render :nothing => true
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
render :nothing => true
|
16
|
+
end
|
17
|
+
|
18
|
+
def edit
|
19
|
+
render :nothing => true
|
20
|
+
end
|
21
|
+
|
22
|
+
def update
|
23
|
+
render :nothing => true
|
24
|
+
end
|
25
|
+
|
26
|
+
def destroy
|
27
|
+
render :nothing => true
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Thing < ActiveRecord::Base
|
2
|
+
include Heimdallr::Model
|
3
|
+
|
4
|
+
belongs_to :entity
|
5
|
+
|
6
|
+
restrict do |user, record|
|
7
|
+
if user.admin
|
8
|
+
scope :fetch
|
9
|
+
scope :delete
|
10
|
+
can [:view, :create, :update]
|
11
|
+
else
|
12
|
+
scope :fetch, -> { where('public = ? or owner_id = ?', true, user.id) }
|
13
|
+
scope :delete, -> { where('owner_id = ?', user.id) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -0,0 +1,382 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Heimdallr::ResourceImplementation do
|
4
|
+
let(:controller) { Object.new }
|
5
|
+
let(:params) { HashWithIndifferentAccess.new :controller => :entities }
|
6
|
+
let(:entity) { stub!.id{1}.subject }
|
7
|
+
before do
|
8
|
+
stub(controller).params { params }
|
9
|
+
stub(controller).skip_authorization_check? { false }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#load_resource' do
|
13
|
+
it "loads and assigns the resource to an instance variable for show action" do
|
14
|
+
params.merge! :action => 'show', :id => entity.id
|
15
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
16
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
17
|
+
resource.load_resource
|
18
|
+
controller.instance_variable_get(:@entity).should == entity
|
19
|
+
end
|
20
|
+
|
21
|
+
it "loads and assigns the resource to an instance variable for edit action" do
|
22
|
+
params.merge! :action => 'edit', :id => entity.id
|
23
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
24
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
25
|
+
resource.load_resource
|
26
|
+
controller.instance_variable_get(:@entity).should == entity
|
27
|
+
end
|
28
|
+
|
29
|
+
it "loads and assigns the resource to an instance variable for update action" do
|
30
|
+
params.merge! :action => 'edit', :id => entity.id
|
31
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
32
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
33
|
+
resource.load_resource
|
34
|
+
controller.instance_variable_get(:@entity).should == entity
|
35
|
+
end
|
36
|
+
|
37
|
+
it "loads and assigns the resource to an instance variable for destroy action" do
|
38
|
+
params.merge! :action => 'destroy', :id => entity.id
|
39
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
40
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
41
|
+
resource.load_resource
|
42
|
+
controller.instance_variable_get(:@entity).should == entity
|
43
|
+
end
|
44
|
+
|
45
|
+
it "builds and assigns a new resource for new action" do
|
46
|
+
params.merge! :action => 'new'
|
47
|
+
mock(Entity).new({}) { :new_entity }
|
48
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
49
|
+
resource.load_resource
|
50
|
+
controller.instance_variable_get(:@entity).should == :new_entity
|
51
|
+
end
|
52
|
+
|
53
|
+
it "builds and assigns a new resource for create action" do
|
54
|
+
params.merge! :action => 'create', :entity => {:name => 'foo'}
|
55
|
+
mock(Entity).new('name' => 'foo') { :new_entity }
|
56
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
57
|
+
resource.load_resource
|
58
|
+
controller.instance_variable_get(:@entity).should == :new_entity
|
59
|
+
end
|
60
|
+
|
61
|
+
it "loads and assigns a resource collection for index action" do
|
62
|
+
params.merge! :action => 'index'
|
63
|
+
mock(Entity).scoped { :entity_collection }
|
64
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
65
|
+
resource.load_resource
|
66
|
+
controller.instance_variable_get(:@entities).should == :entity_collection
|
67
|
+
end
|
68
|
+
|
69
|
+
it "loads and assigns a namespaced resource" do
|
70
|
+
params.merge! :action => 'show', :id => entity.id
|
71
|
+
module SomeProject
|
72
|
+
class Entity < ::Entity; end
|
73
|
+
end
|
74
|
+
stub(SomeProject::Entity).scoped.mock!.find(entity.id) { entity }
|
75
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'some_project/entity'
|
76
|
+
resource.load_resource
|
77
|
+
controller.instance_variable_get(:@some_project_entity).should == entity
|
78
|
+
end
|
79
|
+
|
80
|
+
it "loads the resource with a custom finder" do
|
81
|
+
params.merge! :action => 'show', :id => entity.id
|
82
|
+
stub(Entity).scoped.mock!.find_by_name(entity.id) { entity }
|
83
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :finder => :find_by_name
|
84
|
+
resource.load_resource
|
85
|
+
controller.instance_variable_get(:@entity).should == entity
|
86
|
+
end
|
87
|
+
|
88
|
+
it "loads and assigns a single resource for custom action by default" do
|
89
|
+
params.merge! :action => 'fetch', :id => entity.id
|
90
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
91
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
92
|
+
resource.load_resource
|
93
|
+
controller.instance_variable_get(:@entity).should == entity
|
94
|
+
end
|
95
|
+
|
96
|
+
it "loads and assigns a collection for custom action if specified in options" do
|
97
|
+
params.merge! :action => 'sort'
|
98
|
+
mock(Entity).scoped { :entity_collection }
|
99
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :collection => [:sort]
|
100
|
+
resource.load_resource
|
101
|
+
controller.instance_variable_get(:@entities).should == :entity_collection
|
102
|
+
end
|
103
|
+
|
104
|
+
it "builds and assigns a new resource for custom action if specified in options" do
|
105
|
+
params.merge! :action => 'generate', :entity => {:name => 'foo'}
|
106
|
+
mock(Entity).new('name' => 'foo') { :new_entity }
|
107
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :new_record => [:generate]
|
108
|
+
resource.load_resource
|
109
|
+
controller.instance_variable_get(:@entity).should == :new_entity
|
110
|
+
end
|
111
|
+
|
112
|
+
it "doesn't assign the resource to an instance variable if it is already assigned" do
|
113
|
+
params.merge! :action => 'show', :id => entity.id
|
114
|
+
controller.instance_variable_set :@entity, :different_entity
|
115
|
+
stub(Entity).scoped.stub!.find(entity.id) { entity }
|
116
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
117
|
+
resource.load_resource
|
118
|
+
controller.instance_variable_get(:@entity).should == :different_entity
|
119
|
+
end
|
120
|
+
|
121
|
+
it "loads and assigns a resource through the association of another parent resource" do
|
122
|
+
thing = stub!.id{1}.subject
|
123
|
+
params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
|
124
|
+
controller.instance_variable_set(:@entity, entity)
|
125
|
+
stub(entity).things.mock!.find(thing.id) { thing }
|
126
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
|
127
|
+
resource.load_resource
|
128
|
+
controller.instance_variable_get(:@thing).should == thing
|
129
|
+
end
|
130
|
+
|
131
|
+
it "loads and assigns the parent resource if :through option is provided" do
|
132
|
+
params.merge! :controller => :things, :action => 'index', :entity_id => entity.id
|
133
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
134
|
+
stub(entity).things
|
135
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
|
136
|
+
resource.load_resource
|
137
|
+
controller.instance_variable_get(:@entity).should == entity
|
138
|
+
end
|
139
|
+
|
140
|
+
it "loads the resource directly if the parent isn't found and :shallow option is true" do
|
141
|
+
thing = stub!.id{1}.subject
|
142
|
+
params.merge! :controller => :things, :action => 'show', :id => thing.id
|
143
|
+
stub(Thing).scoped.mock!.find(thing.id) { thing }
|
144
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :shallow => true
|
145
|
+
resource.load_resource
|
146
|
+
controller.instance_variable_get(:@thing).should == thing
|
147
|
+
end
|
148
|
+
|
149
|
+
it "raises an error when the parent's id is not provided" do
|
150
|
+
params.merge! :controller => :things, :action => 'show', :id => 1
|
151
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity'
|
152
|
+
expect { resource.load_resource }.to raise_error(RuntimeError)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "loads through the first parent found when multiple are given" do
|
156
|
+
thing = stub!.id{1}.subject
|
157
|
+
params.merge! :controller => :things, :action => 'show', :id => thing.id
|
158
|
+
class Nothing; end
|
159
|
+
stub(Nothing).scoped
|
160
|
+
controller.instance_variable_set(:@entity, entity)
|
161
|
+
controller.instance_variable_set(:@user, Object.new)
|
162
|
+
stub(entity).things.mock!.find(thing.id) { thing }
|
163
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => [:nothing, :entity, :user]
|
164
|
+
resource.load_resource
|
165
|
+
controller.instance_variable_get(:@thing).should == thing
|
166
|
+
end
|
167
|
+
|
168
|
+
it "loads through has_one association with :singleton option" do
|
169
|
+
thing = stub!.id{1}.subject
|
170
|
+
params.merge! :controller => :things, :action => 'show'
|
171
|
+
controller.instance_variable_set(:@entity, entity)
|
172
|
+
mock(entity).thing { thing }
|
173
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
|
174
|
+
resource.load_resource
|
175
|
+
controller.instance_variable_get(:@thing).should == thing
|
176
|
+
end
|
177
|
+
|
178
|
+
it "builds a record through has_one association with :singleton option" do
|
179
|
+
params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
|
180
|
+
controller.instance_variable_set(:@entity, entity)
|
181
|
+
thing = stub!.id{1}.subject
|
182
|
+
stub(entity).thing { nil }
|
183
|
+
mock(entity).build_thing('name' => 'foo') { thing }
|
184
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
|
185
|
+
resource.load_resource
|
186
|
+
controller.instance_variable_get(:@thing).should == thing
|
187
|
+
end
|
188
|
+
|
189
|
+
it "builds a record with correct method name with :singleton and :through_association options" do
|
190
|
+
params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
|
191
|
+
controller.instance_variable_set(:@entity, entity)
|
192
|
+
thing = stub!.id{1}.subject
|
193
|
+
stub(entity).stuff { nil }
|
194
|
+
mock(entity).build_stuff('name' => 'foo') { thing }
|
195
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :through_association => :stuff
|
196
|
+
resource.load_resource
|
197
|
+
controller.instance_variable_get(:@thing).should == thing
|
198
|
+
end
|
199
|
+
|
200
|
+
it "doesn't build a record through has_one association with :singleton option if one already exists because it can cause it to delete it in the database" do
|
201
|
+
params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
|
202
|
+
controller.instance_variable_set(:@entity, entity)
|
203
|
+
thing = stub!.id{1}.subject
|
204
|
+
mock(entity).thing { thing }
|
205
|
+
mock(thing).assign_attributes 'name' => 'foo'
|
206
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true
|
207
|
+
resource.load_resource
|
208
|
+
controller.instance_variable_get(:@thing).should == thing
|
209
|
+
end
|
210
|
+
|
211
|
+
it "loads through has_one association with :singleton and :shallow options" do
|
212
|
+
thing = stub!.id{1}.subject
|
213
|
+
params.merge! :controller => :things, :action => 'show', :id => thing.id
|
214
|
+
stub(Thing).scoped.mock!.find(thing.id) { thing }
|
215
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
|
216
|
+
resource.load_resource
|
217
|
+
controller.instance_variable_get(:@thing).should == thing
|
218
|
+
end
|
219
|
+
|
220
|
+
it "builds a record through has_one association with :singleton and :shallow options" do
|
221
|
+
params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
|
222
|
+
stub(Thing).scoped.mock!.new('name' => 'foo') { :new_thing }
|
223
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
|
224
|
+
resource.load_resource
|
225
|
+
controller.instance_variable_get(:@thing).should == :new_thing
|
226
|
+
end
|
227
|
+
|
228
|
+
it "builds a record through has_one association with :singleton and :shallow options even if the parent is present" do
|
229
|
+
params.merge! :controller => :things, :action => 'create', :thing => {:name => 'foo'}
|
230
|
+
controller.instance_variable_set(:@entity, entity)
|
231
|
+
stub(entity).thing { nil }
|
232
|
+
mock(entity).build_thing('name' => 'foo') { :new_thing }
|
233
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :singleton => true, :shallow => :true
|
234
|
+
resource.load_resource
|
235
|
+
controller.instance_variable_get(:@thing).should == :new_thing
|
236
|
+
end
|
237
|
+
|
238
|
+
it "loads through custom association if :through_association option is provided" do
|
239
|
+
thing = stub!.id{1}.subject
|
240
|
+
params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
|
241
|
+
controller.instance_variable_set(:@entity, entity)
|
242
|
+
stub(entity).stuff.mock!.find(thing.id) { thing }
|
243
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :through_association => :stuff
|
244
|
+
resource.load_resource
|
245
|
+
controller.instance_variable_get(:@thing).should == thing
|
246
|
+
end
|
247
|
+
|
248
|
+
it "loads through custom association if both :through_association and :singleton options are provided" do
|
249
|
+
thing = stub!.id{1}.subject
|
250
|
+
params.merge! :controller => :things, :action => 'show', :entity_id => entity.id, :id => thing.id
|
251
|
+
controller.instance_variable_set(:@entity, entity)
|
252
|
+
mock(entity).stuff { thing }
|
253
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'thing', :through => 'entity', :through_association => :stuff, :singleton => true
|
254
|
+
resource.load_resource
|
255
|
+
controller.instance_variable_get(:@thing).should == thing
|
256
|
+
end
|
257
|
+
|
258
|
+
it "loads and assigns a resource using custom instance name" do
|
259
|
+
params.merge! :action => 'show', :id => entity.id
|
260
|
+
stub(Entity).scoped.mock!.find(entity.id) { entity }
|
261
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :instance_name => :something
|
262
|
+
resource.load_resource
|
263
|
+
controller.instance_variable_get(:@something).should == entity
|
264
|
+
end
|
265
|
+
|
266
|
+
it "loads and assigns a resource collection using custom instance name" do
|
267
|
+
params.merge! :action => 'index'
|
268
|
+
mock(Entity).scoped { :entity_collection }
|
269
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity', :instance_name => :something
|
270
|
+
resource.load_resource
|
271
|
+
controller.instance_variable_get(:@somethings).should == :entity_collection
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe '#load_and_authorize_resource' do
|
276
|
+
let(:user) { stub!.id{1}.subject }
|
277
|
+
before do
|
278
|
+
stub(user).admin { false }
|
279
|
+
stub(controller).security_context { user }
|
280
|
+
end
|
281
|
+
|
282
|
+
it "calls #restrict on the loaded resource" do
|
283
|
+
params.merge! :action => 'show', :id => entity.id
|
284
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
285
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
286
|
+
resource.load_and_authorize_resource
|
287
|
+
end
|
288
|
+
|
289
|
+
it "raises AccessDenied when calling :new action for resource that can't be created" do
|
290
|
+
params.merge! :action => 'new'
|
291
|
+
mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
|
292
|
+
stub(entity).assign_attributes
|
293
|
+
mock(entity).creatable? { false }
|
294
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
295
|
+
expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "raises AccessDenied when creating a resource that can't be created" do
|
299
|
+
params.merge! :action => 'create'
|
300
|
+
mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
|
301
|
+
stub(entity).assign_attributes
|
302
|
+
mock(entity).creatable? { false }
|
303
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
304
|
+
expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
|
305
|
+
end
|
306
|
+
|
307
|
+
it "raises AccessDenied when calling :edit action for resource that can't be updated" do
|
308
|
+
params.merge! :action => 'edit', :id => entity.id
|
309
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
310
|
+
mock(entity).modifiable? { false }
|
311
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
312
|
+
expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
|
313
|
+
end
|
314
|
+
|
315
|
+
it "raises AccessDenied when updating a resource that can't be updated" do
|
316
|
+
params.merge! :action => 'update', :id => entity.id
|
317
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
318
|
+
mock(entity).modifiable? { false }
|
319
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
320
|
+
expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
|
321
|
+
end
|
322
|
+
|
323
|
+
it "raises AccessDenied when destroying a resource that can't be destroyed" do
|
324
|
+
params.merge! :action => 'destroy', :id => entity.id
|
325
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
326
|
+
mock(entity).destroyable? { false }
|
327
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
328
|
+
expect { resource.load_and_authorize_resource }.to raise_error(Heimdallr::AccessDenied)
|
329
|
+
end
|
330
|
+
|
331
|
+
it "fixates certain attributes of a new resource" do
|
332
|
+
params.merge! :action => 'new', :entity => {:name => 'foo'}
|
333
|
+
mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
|
334
|
+
mock(entity).creatable? { true }
|
335
|
+
fixtures = {:create => {:name => 'bar'}}
|
336
|
+
stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
|
337
|
+
stub(entity).assign_attributes('name' => 'foo')
|
338
|
+
mock(entity).assign_attributes(fixtures[:create])
|
339
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
340
|
+
resource.load_and_authorize_resource
|
341
|
+
controller.instance_variable_get(:@entity) == entity
|
342
|
+
end
|
343
|
+
|
344
|
+
it "fixates certain attributes of an updating resource" do
|
345
|
+
params.merge! :action => 'update', :id => entity.id, :entity => {:name => 'foo'}
|
346
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
347
|
+
mock(entity).modifiable? { true }
|
348
|
+
fixtures = {:update => {:name => 'bar'}}
|
349
|
+
stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
|
350
|
+
stub(entity).assign_attributes('name' => 'foo')
|
351
|
+
mock(entity).assign_attributes(fixtures[:update])
|
352
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
353
|
+
resource.load_and_authorize_resource
|
354
|
+
controller.instance_variable_get(:@entity) == entity
|
355
|
+
end
|
356
|
+
|
357
|
+
context "when controller.skip_authorization_check? is true" do
|
358
|
+
before { stub(controller).skip_authorization_check? { true } }
|
359
|
+
|
360
|
+
it "doesn't raise AccessDenied" do
|
361
|
+
params.merge! :action => 'destroy', :id => entity.id
|
362
|
+
mock(Entity).restrict(controller.security_context).stub!.find(entity.id) { entity }
|
363
|
+
stub(entity).destroyable? { false }
|
364
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
365
|
+
expect { resource.load_and_authorize_resource }.not_to raise_error(Heimdallr::AccessDenied)
|
366
|
+
end
|
367
|
+
|
368
|
+
it "doesn't fixate attributes" do
|
369
|
+
params.merge! :action => 'new', :entity => {:name => 'foo'}
|
370
|
+
mock(Entity).new.mock!.restrict(controller.security_context, {}) { entity }
|
371
|
+
stub(entity).creatable? { true }
|
372
|
+
fixtures = {:create => {:name => 'bar'}}
|
373
|
+
stub(entity).reflect_on_security { {:restrictions => stub!.fixtures{fixtures}.subject} }
|
374
|
+
stub(entity).assign_attributes('name' => 'foo')
|
375
|
+
dont_allow(entity).assign_attributes(fixtures[:create])
|
376
|
+
resource = Heimdallr::ResourceImplementation.new controller, :resource => 'entity'
|
377
|
+
resource.load_and_authorize_resource
|
378
|
+
controller.instance_variable_get(:@entity) == entity
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|