skinny_controllers 0.3.3 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +59 -2
- data/lib/skinny_controllers/operation/default.rb +34 -1
- data/lib/skinny_controllers/operation/model_helpers.rb +13 -1
- data/lib/skinny_controllers/policy/allow_all.rb +11 -3
- data/lib/skinny_controllers/policy/deny_all.rb +11 -3
- data/lib/skinny_controllers/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52131d9a1e993b5046ea0104928cce55b32cfa8e
|
4
|
+
data.tar.gz: dbcc1157c9129361df79a71b2f8e5c103a9d94e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77aa4ae8568318784f6092a5d8f109f726a2a53134e5217ffe0b18ca1ab31bd63c81121ed62ca58c632f716221b587606a40b510768fd9c2d7743cb56307f51a
|
7
|
+
data.tar.gz: 968f986aa8a475bd965df72c49252b5c073466cca3b8a59d2b68293da93275c3b17c0a85fbb1bdfe49fcdf11d433d08a6c7f39a69027c607e3c390eb918797a6
|
data/README.md
CHANGED
@@ -11,6 +11,8 @@ The goal of this project is to help API apps be more slim, and separate logic as
|
|
11
11
|
|
12
12
|
This gem is inspired by [trailblazer](https://github.com/apotonick/trailblazer), following similar patterns, yet allowing the structure of the rails app to not be entirely overhauled.
|
13
13
|
|
14
|
+
Please note that this is a work in progress, and that the defaults are subject to change. If you have an idea or suggestion for improved defaults, please submit an issue or pull request. :-)
|
15
|
+
|
14
16
|
# Installation
|
15
17
|
|
16
18
|
```ruby
|
@@ -37,10 +39,11 @@ The above does a multitude of assumptions to make sure that you can type the lea
|
|
37
39
|
|
38
40
|
1. Your controller name is based off your model name (configurable per controller)
|
39
41
|
2. Any defined policies or operations follow the formats (though they don't have to exist):
|
40
|
-
-
|
41
|
-
-
|
42
|
+
- `class #{Model.name}Policy`
|
43
|
+
- `module #{Model.name}Operations`
|
42
44
|
3. Your model responds to `find`, and `where`
|
43
45
|
4. Your model responds to `is_accessible_to?`. This can be changed at `SkinnyControllers.accessible_to_method`
|
46
|
+
5. If relying on the default / implicit operations for create and update, the params key for your model's changes much be formatted as `{ Model.name.underscore => { attributes }}``
|
44
47
|
|
45
48
|
### Your model name might be different from your resource name
|
46
49
|
Lets say you have a JSON API resource that you'd like to render that has some additional/subset of data.
|
@@ -104,6 +107,60 @@ module UserOperations
|
|
104
107
|
end
|
105
108
|
```
|
106
109
|
|
110
|
+
### Creating
|
111
|
+
|
112
|
+
To achieve default functionality, this operation *may* be defined -- though, it is implicitly assumed to function this way if not defined.
|
113
|
+
```ruby
|
114
|
+
module UserOperations
|
115
|
+
class Create < SkinnyControllers::Operation::Base
|
116
|
+
def run
|
117
|
+
return unless allowed?
|
118
|
+
@model = model_class.new(model_params)
|
119
|
+
@model.save
|
120
|
+
@model # or just `model`
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
### Updating
|
127
|
+
```ruby
|
128
|
+
module UserOperations
|
129
|
+
class Create < SkinnyControllers::Operation::Base
|
130
|
+
def run
|
131
|
+
return unless allowed?
|
132
|
+
model.update(model_params)
|
133
|
+
model
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
### Deleting
|
140
|
+
|
141
|
+
Goal: Users should only be able to delete themselves
|
142
|
+
|
143
|
+
To achieve default functionality, this operation *may* be defined -- though, it is implicitly assumed to function this way if not defined.
|
144
|
+
```ruby
|
145
|
+
module UserOperations
|
146
|
+
class Delete < SkinnyControllers::Operation::Base
|
147
|
+
def run
|
148
|
+
model.destroy if allowed?
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
And given that this method exists on the `User` model:
|
155
|
+
```ruby
|
156
|
+
# realistically, you'd only want users to be able to access themselves
|
157
|
+
def is_accessible_to?(user)
|
158
|
+
self.id == user.id
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
Making a call to the destroy action on the `UsersController` will only succeed if the user trying to delete themselves. (Possibly to 'cancel their account')
|
163
|
+
|
107
164
|
|
108
165
|
## Defining Policies
|
109
166
|
|
@@ -2,7 +2,40 @@ module SkinnyControllers
|
|
2
2
|
module Operation
|
3
3
|
class Default < Base
|
4
4
|
def run
|
5
|
-
|
5
|
+
return unless allowed?
|
6
|
+
|
7
|
+
# Note that for explicitly defined operations,
|
8
|
+
# There should be a different operation for each
|
9
|
+
# action.
|
10
|
+
#
|
11
|
+
# e.g.:
|
12
|
+
# - EventOperations::Create
|
13
|
+
# - EventOperations::Update
|
14
|
+
# - EventOperations::Destroy
|
15
|
+
if creating?
|
16
|
+
@model = model_class.new(model_params)
|
17
|
+
@model.save
|
18
|
+
elsif updating?
|
19
|
+
model.update(model_params)
|
20
|
+
elsif destroying?
|
21
|
+
model.destroy
|
22
|
+
end
|
23
|
+
|
24
|
+
model
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def creating?
|
30
|
+
params[:action] == 'create'
|
31
|
+
end
|
32
|
+
|
33
|
+
def updating?
|
34
|
+
params[:action] == 'update'
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroying?
|
38
|
+
params[:action] == 'destroy'
|
6
39
|
end
|
7
40
|
end
|
8
41
|
end
|
@@ -23,6 +23,18 @@ module SkinnyControllers
|
|
23
23
|
params.slice(*keys).symbolize_keys
|
24
24
|
end
|
25
25
|
|
26
|
+
# TODO: add a way to use existing strong parameters methods
|
27
|
+
def model_params
|
28
|
+
# for mass-assignment, rails doesn't accept
|
29
|
+
# stringified keys.
|
30
|
+
# TODO: why did the params hash lose its indifferent access
|
31
|
+
@model_params ||= params[model_param_name].symbolize_keys
|
32
|
+
end
|
33
|
+
|
34
|
+
def model_param_name
|
35
|
+
model_name.underscore
|
36
|
+
end
|
37
|
+
|
26
38
|
def scoped_model(scoped_params)
|
27
39
|
unless @scoped_model
|
28
40
|
klass_name = scoped_params[:type]
|
@@ -42,7 +54,7 @@ module SkinnyControllers
|
|
42
54
|
# It's better to filter in sql, than in the app, so if there is
|
43
55
|
# a way to do the filtering in active query, do that. This will help
|
44
56
|
# mitigate n+1 query scenarios
|
45
|
-
return ar_proxy.
|
57
|
+
return ar_proxy.send(SkinnyControllers.accessible_to_scope, current_user)
|
46
58
|
end
|
47
59
|
|
48
60
|
ar_proxy
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module SkinnyControllers
|
2
2
|
module Policy
|
3
3
|
class AllowAll < Base
|
4
|
-
def default
|
5
|
-
|
6
|
-
|
4
|
+
def default?
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
def read?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def read_all?
|
13
|
+
true
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module SkinnyControllers
|
2
2
|
module Policy
|
3
3
|
class DenyAll < Base
|
4
|
-
def default
|
5
|
-
|
6
|
-
|
4
|
+
def default?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def read?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def read_all?
|
13
|
+
false
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skinny_controllers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- L. Preston Sego III
|
@@ -224,5 +224,5 @@ rubyforge_project:
|
|
224
224
|
rubygems_version: 2.4.8
|
225
225
|
signing_key:
|
226
226
|
specification_version: 4
|
227
|
-
summary: SkinnyControllers-0.
|
227
|
+
summary: SkinnyControllers-0.4.0
|
228
228
|
test_files: []
|