sweet_actions 0.1.5 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/README.md +216 -175
- data/lib/generators/sweet_actions/templates/base_action.rb +4 -0
- data/lib/generators/sweet_actions/templates/collect_action.rb +7 -8
- data/lib/generators/sweet_actions/templates/create_action.rb +10 -11
- data/lib/generators/sweet_actions/templates/destroy_action.rb +10 -11
- data/lib/generators/sweet_actions/templates/show_action.rb +7 -8
- data/lib/generators/sweet_actions/templates/update_action.rb +11 -12
- data/lib/sweet_actions/.DS_Store +0 -0
- data/lib/sweet_actions/action.rb +32 -0
- data/lib/sweet_actions/action_factory.rb +4 -2
- data/lib/sweet_actions/{authorization_concerns.rb → authorization.rb} +2 -2
- data/lib/sweet_actions/controller_concerns.rb +0 -1
- data/lib/sweet_actions/exceptions.rb +13 -0
- data/lib/sweet_actions/json/.DS_Store +0 -0
- data/lib/sweet_actions/json/base_action.rb +41 -0
- data/lib/sweet_actions/json/collect_action.rb +13 -0
- data/lib/sweet_actions/json/create_action.rb +18 -0
- data/lib/sweet_actions/json/destroy_action.rb +13 -0
- data/lib/sweet_actions/json/show_action.rb +13 -0
- data/lib/sweet_actions/json/update_action.rb +18 -0
- data/lib/sweet_actions/{rest_concerns.rb → resource.rb} +3 -5
- data/lib/sweet_actions/rest/.DS_Store +0 -0
- data/lib/sweet_actions/rest/base.rb +8 -0
- data/lib/sweet_actions/rest/collect.rb +14 -0
- data/lib/sweet_actions/rest/create.rb +14 -0
- data/lib/sweet_actions/rest/destroy.rb +25 -0
- data/lib/sweet_actions/rest/find.rb +13 -0
- data/lib/sweet_actions/rest/multiple.rb +9 -0
- data/lib/sweet_actions/rest/read.rb +19 -0
- data/lib/sweet_actions/rest/save.rb +54 -0
- data/lib/sweet_actions/rest/show.rb +8 -0
- data/lib/sweet_actions/rest/singular.rb +9 -0
- data/lib/sweet_actions/rest/update.rb +15 -0
- data/lib/sweet_actions/{rest_serializer_concerns.rb → serialize.rb} +12 -3
- data/lib/sweet_actions/version.rb +1 -1
- data/lib/sweet_actions.rb +27 -13
- data/sweet_actions.gemspec +3 -0
- metadata +55 -14
- data/lib/generators/rails/resource_override.rb +0 -10
- data/lib/sweet_actions/api_action.rb +0 -63
- data/lib/sweet_actions/collect_action.rb +0 -11
- data/lib/sweet_actions/create_action.rb +0 -10
- data/lib/sweet_actions/destroy_action.rb +0 -19
- data/lib/sweet_actions/read_concerns.rb +0 -14
- data/lib/sweet_actions/save_concerns.rb +0 -51
- data/lib/sweet_actions/show_action.rb +0 -9
- data/lib/sweet_actions/update_action.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2460958332f8a5291485d228c95da9b3c6f38a9
|
4
|
+
data.tar.gz: 977ce5b64b0d74e726ebc212ab259bc3db1d26e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2994cd3afa31f96da8f23a90af9399ff029da96c9c813fab812c34f2c07492a78b891e7b75ff02d4b36895ba6ae6c157ee2223e99817470a8c4e2d002a7006de
|
7
|
+
data.tar.gz: 568fc472e0f7ba8476ad86e359650f730a128f279fb01aca0e562fb5926e65cafe468f7f812a81894938b041bf63cf489f84cafb4f0bc072fc35b7155b007936
|
data/.DS_Store
ADDED
Binary file
|
data/README.md
CHANGED
@@ -1,6 +1,174 @@
|
|
1
1
|
# Sweet Actions
|
2
2
|
|
3
|
-
##
|
3
|
+
## Introduction
|
4
|
+
Controller actions (`events#create`) tend to have more in common with their cousins (`articles#create`) than their siblings (`events#show`). Because of this, we think actions should be classes instead of methods. This makes it possible for actions to take advantage of common Object Oriented principles like Inheritance and Composition.
|
5
|
+
|
6
|
+
The end result of this approach is that resource-specific controllers and actions often don't even need to exist - their logic is abstracted to parent actions.
|
7
|
+
|
8
|
+
Work smart not hard right?
|
9
|
+
|
10
|
+
Let's take a look at how that's possible.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
### 1. Install Gem
|
15
|
+
|
16
|
+
Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'sweet_actions'
|
20
|
+
gem 'active_model_serializers'
|
21
|
+
gem 'decanter'
|
22
|
+
```
|
23
|
+
|
24
|
+
Terminal:
|
25
|
+
|
26
|
+
```
|
27
|
+
bundle
|
28
|
+
bundle exec rails g sweet_actions:install
|
29
|
+
```
|
30
|
+
|
31
|
+
This command generates a folder at `app/actions` with the following structure:
|
32
|
+
|
33
|
+
```
|
34
|
+
- base_action.rb
|
35
|
+
- collect_action.rb
|
36
|
+
- create_action.rb
|
37
|
+
- destroy_action.rb
|
38
|
+
- show_action.rb
|
39
|
+
- update_action.rb
|
40
|
+
```
|
41
|
+
|
42
|
+
### 2. Generate Resource
|
43
|
+
|
44
|
+
```
|
45
|
+
rails g model Event title:string start_date:date
|
46
|
+
bundle exec rake db:migrate
|
47
|
+
rails g decanter Event title:string start_date:date
|
48
|
+
rails g serializer Event title:string start_date:date
|
49
|
+
rails g actions Events
|
50
|
+
```
|
51
|
+
|
52
|
+
This last command (`rails g actions events`) generates a folder at `app/actions/events` with the following structure:
|
53
|
+
|
54
|
+
```
|
55
|
+
- events/
|
56
|
+
- collect.rb
|
57
|
+
- create.rb
|
58
|
+
- destroy.rb
|
59
|
+
- show.rb
|
60
|
+
- update.rb
|
61
|
+
```
|
62
|
+
|
63
|
+
### 3. Add Routes
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
Rails.application.routes.draw do
|
67
|
+
scope :api do
|
68
|
+
scope :v1 do
|
69
|
+
create_sweet_actions(:events)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
### 4. Profit
|
76
|
+
|
77
|
+
```
|
78
|
+
rails s
|
79
|
+
```
|
80
|
+
|
81
|
+
Using Postman, submit the following request:
|
82
|
+
|
83
|
+
POST to localhost:3000/api/v1/events
|
84
|
+
|
85
|
+
```json
|
86
|
+
{
|
87
|
+
"event": {
|
88
|
+
"title": "My sweet event",
|
89
|
+
"start_date": "01/18/2018"
|
90
|
+
}
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
You should get a response like so:
|
95
|
+
|
96
|
+
```json
|
97
|
+
{
|
98
|
+
"type": "event",
|
99
|
+
"attributes": {
|
100
|
+
"id": 1,
|
101
|
+
"title": "My sweet event",
|
102
|
+
"start_date": "2018-01-18"
|
103
|
+
}
|
104
|
+
}
|
105
|
+
```
|
106
|
+
|
107
|
+
## Default REST Actions
|
108
|
+
|
109
|
+
For a given resource, we provide five RESTful actions:
|
110
|
+
|
111
|
+
```
|
112
|
+
Collect: GET '/events'
|
113
|
+
Create: POST '/events'
|
114
|
+
Show: GET '/events/:id'
|
115
|
+
Update: PUT '/events/:id'
|
116
|
+
Destroy: DELETE '/events/:id'
|
117
|
+
```
|
118
|
+
|
119
|
+
Many of these actions have shared behavior, which we abstract for you:
|
120
|
+
- Authorization of resource (cancancan for example)
|
121
|
+
- Create and Update need to be able to properly respond with error information when save does not succeed
|
122
|
+
- Create and Update rely on decanted params
|
123
|
+
- Serialization of resource
|
124
|
+
|
125
|
+
## Creating One-Off Actions
|
126
|
+
|
127
|
+
For actions that are not RESTful (i.e. not one of the five listed above), you can still use `sweet_actions`. For example, let's say you want to create the action `events#export`.
|
128
|
+
|
129
|
+
1. Create a new file at app/actions/events/export.rb:
|
130
|
+
2. Implement `action` method that responds with a response hash
|
131
|
+
3. Create the route
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
# app/actions/events/export.rb:
|
135
|
+
module Events
|
136
|
+
class Export < SweetActions::JSON::BaseAction
|
137
|
+
def action
|
138
|
+
{
|
139
|
+
success: true
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# config/routes.rb
|
148
|
+
Rails.application.routes.draw do
|
149
|
+
scope :api
|
150
|
+
scope :v1
|
151
|
+
get '/events/export' => 'sweet_actions#export', resource_class: 'Event'
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
Using a tool like Postman, submit the following request:
|
158
|
+
|
159
|
+
```
|
160
|
+
GET to localhost:3000/api/v1/events/export
|
161
|
+
```
|
162
|
+
|
163
|
+
You should get a response like so:
|
164
|
+
|
165
|
+
```json
|
166
|
+
{
|
167
|
+
success: true
|
168
|
+
}
|
169
|
+
```
|
170
|
+
|
171
|
+
## The Idea Explained in Detail
|
4
172
|
|
5
173
|
In a RESTful context, controller actions tend to have more in common with the same actions belonging to other resources than other actions belonging to the same resource. For example, let's say we have two resources in our app: Events and Articles.
|
6
174
|
|
@@ -16,7 +184,7 @@ We would argue that #2 has more in common than #1. Both events#create and articl
|
|
16
184
|
3. Persist the new record
|
17
185
|
4. Respond with new record (if successful) or error information (if unsuccessful) in the JSON
|
18
186
|
|
19
|
-
|
187
|
+
Rails pushes us to organize our actions as methods inside a resource based controller like below. With this approach we cannot take advantage of basic Object Oriented programming concepts like Inheritance and Modules as it relates to specific actions.
|
20
188
|
|
21
189
|
```ruby
|
22
190
|
class EventsController < ApplicationController
|
@@ -61,33 +229,22 @@ class ArticlesController < ApplicationController
|
|
61
229
|
end
|
62
230
|
```
|
63
231
|
|
64
|
-
Instead, we propose a strategy
|
232
|
+
Instead, we propose a strategy where the actions themselves are classes. This would allow us have multiple layers of abstraction like so:
|
65
233
|
|
66
|
-
|
67
|
-
|
68
|
-
module SweetActions
|
69
|
-
class CreateAction < ApiAction
|
70
|
-
def action
|
71
|
-
@resource = set_resource
|
72
|
-
authorize
|
73
|
-
validate_and_save ? success : failure
|
74
|
-
end
|
234
|
+
1. **Generic Logic** (logic that applies to all apps that use SweetActions):
|
235
|
+
- `class SweetActions::JSON::CreateAction`
|
75
236
|
|
76
|
-
|
77
|
-
|
78
|
-
end
|
237
|
+
2. **Application Logic**: logic that applies to all create actions in your app:
|
238
|
+
- `class CreateAction < SweetActions::JSON::CreateAction`
|
79
239
|
|
80
|
-
|
81
|
-
class
|
82
|
-
def set_resource
|
83
|
-
resource_class.new(resource_params)
|
84
|
-
end
|
240
|
+
3. **Resource Logic**: logic that applies to a specific resource (e.g. Events) in your app
|
241
|
+
- `class Events::Create < CreateAction`
|
85
242
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
243
|
+
With this approach, we often won't even need to implement resource specific actions. This is because by default our `Events::Create` action will inherit all the functionality it needs. Only when there are deviances from the norm do we implement resource specific classes and in those cases, we need only override the methods that correspond with the deviance.
|
244
|
+
|
245
|
+
For example, let's say we want to send an email when an event is created. It's as easy as overriding the `after_save` hook:
|
90
246
|
|
247
|
+
```ruby
|
91
248
|
# resource logic for create (app/actions/events/create.rb)
|
92
249
|
module Events
|
93
250
|
class Create < CreateAction
|
@@ -98,182 +255,66 @@ module Events
|
|
98
255
|
end
|
99
256
|
```
|
100
257
|
|
101
|
-
|
102
|
-
|
103
|
-
- Generic create logic: SweetActions::CreateActions
|
104
|
-
- App create logic: CreateAction
|
105
|
-
- Resource create logic: Events::Create
|
106
|
-
|
107
|
-
|
108
|
-
As you can see, we can abstract most of the `create` logic to be shared across resources, which means you **only need to write the code that is unique about this create action vs. other create actions**.
|
109
|
-
|
110
|
-
## Default REST Actions
|
111
|
-
|
112
|
-
For a given resource...
|
113
|
-
- Collect: list items
|
114
|
-
- Create: create new item
|
115
|
-
- Show: show item
|
116
|
-
- Update: update item
|
117
|
-
- Destroy: delete item
|
118
|
-
|
119
|
-
Many of these actions have shared behavior, which we abstract for you:
|
120
|
-
- All require serialization of the resource
|
121
|
-
- Create and Update need to be able to properly respond with error information when save does not succeed
|
122
|
-
- Create and Update rely on decanted params
|
123
|
-
- All require authorization (cancancan)
|
124
|
-
|
125
|
-
## Automatic REST API
|
126
|
-
|
127
|
-
Given an Event model, one can do the following and get a basic RESTful API (assuming we have [decanter](https://github.com/launchpadlab/decanter) and [AMS](https://github.com/rails-api/active_model_serializers):
|
128
|
-
|
129
|
-
- rails g model Event name:string start_date:date
|
130
|
-
- rails g decanter Event name:string start_date:date
|
131
|
-
- rails g serializer Event name:string start_date:date
|
132
|
-
- add the new resource in routes
|
133
|
-
|
134
|
-
With that, you have the following at your disposal:
|
135
|
-
|
136
|
-
Collect: get '/events'
|
137
|
-
Create: post '/events'
|
138
|
-
Show: get '/events/:id'
|
139
|
-
Update: put '/events/:id'
|
140
|
-
Destroy: delete '/events/:id'
|
141
|
-
|
142
|
-
Each of these will respond with a consistent JSON format, including when saves don't succeed.
|
143
|
-
|
144
|
-
## Overriding Default Actions
|
145
|
-
|
146
|
-
Should you choose to override the default behavior (defined in app/sweet_actions/defaults/, ), you need only create your own action like so:
|
147
|
-
|
148
|
-
app/sweet_actions/events/collect.rb
|
149
|
-
|
150
|
-
```
|
151
|
-
module Events
|
152
|
-
class Collect < SweetActions::CollectAction
|
153
|
-
def set_resource
|
154
|
-
Event.all.limit(10)
|
155
|
-
end
|
258
|
+
If we wanted to override all action behavior, we could just implement the `action` method itself:
|
156
259
|
|
157
|
-
|
158
|
-
can?(:read, resource)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
```
|
163
|
-
|
164
|
-
app/sweet_actions/events/create.rb
|
165
|
-
|
166
|
-
```
|
260
|
+
```ruby
|
167
261
|
module Events
|
168
262
|
class Create < CreateAction
|
169
|
-
def
|
170
|
-
Event.new(resource_params)
|
171
|
-
|
172
|
-
|
173
|
-
def authorized?
|
174
|
-
can?(:create, resource)
|
175
|
-
end
|
176
|
-
|
177
|
-
def save
|
178
|
-
resource.save
|
263
|
+
def action
|
264
|
+
event = Event.new(resource_params)
|
265
|
+
event.save ? success(event) : failure
|
179
266
|
end
|
180
267
|
|
181
|
-
def
|
182
|
-
|
268
|
+
def success(event)
|
269
|
+
UserMailer.new_event_confirmation(resource).deliver_later
|
270
|
+
{ success: true, data: { event: event } }
|
183
271
|
end
|
184
272
|
end
|
185
273
|
end
|
186
274
|
```
|
187
275
|
|
188
|
-
|
276
|
+
Under the hood, this is made possible by a structure that looks like the following:
|
189
277
|
|
190
|
-
```
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
278
|
+
```ruby
|
279
|
+
# generic logic for create (sweet_actions gem)
|
280
|
+
module SweetActions
|
281
|
+
module JSON
|
282
|
+
class CreateAction < BaseAction
|
283
|
+
def action
|
284
|
+
@resource = set_resource
|
285
|
+
authorize
|
286
|
+
validate_and_save ? success : failure
|
287
|
+
end
|
288
|
+
|
289
|
+
# ...
|
199
290
|
end
|
200
291
|
end
|
201
292
|
end
|
202
293
|
```
|
203
294
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
Event.find(params[:id])
|
211
|
-
end
|
212
|
-
|
213
|
-
def authorized?
|
214
|
-
can?(:update, resource)
|
215
|
-
end
|
295
|
+
```ruby
|
296
|
+
# app logic for create (app/actions/create_action.rb)
|
297
|
+
class CreateAction < SweetActions::JSON::CreateAction
|
298
|
+
def set_resource
|
299
|
+
resource_class.new(resource_params)
|
300
|
+
end
|
216
301
|
|
217
|
-
|
218
|
-
|
219
|
-
end
|
302
|
+
def authorized?
|
303
|
+
can?(:create, resource)
|
220
304
|
end
|
221
305
|
end
|
222
306
|
```
|
223
307
|
|
224
|
-
|
225
|
-
|
226
|
-
```
|
308
|
+
```ruby
|
309
|
+
# resource logic for create (app/actions/events/create.rb)
|
227
310
|
module Events
|
228
|
-
class
|
229
|
-
def
|
230
|
-
|
231
|
-
end
|
232
|
-
|
233
|
-
def authorized?
|
234
|
-
can?(:destroy, resource)
|
235
|
-
end
|
236
|
-
|
237
|
-
def destroy
|
238
|
-
resource.destroy
|
311
|
+
class Create < CreateAction
|
312
|
+
def after_save
|
313
|
+
UserMailer.new_event_confirmation(resource).deliver_later
|
239
314
|
end
|
240
315
|
end
|
241
316
|
end
|
242
317
|
```
|
243
318
|
|
244
|
-
|
245
|
-
|
246
|
-
### 1. Install Gem
|
247
|
-
|
248
|
-
Gemfile:
|
249
|
-
|
250
|
-
```ruby
|
251
|
-
gem 'sweet_actions'
|
252
|
-
gem 'active_model_serializers'
|
253
|
-
gem 'decanter'
|
254
|
-
```
|
255
|
-
|
256
|
-
Terminal:
|
257
|
-
|
258
|
-
```
|
259
|
-
bundle
|
260
|
-
bundle exec rails g sweet_actions:install
|
261
|
-
```
|
262
|
-
|
263
|
-
### 2. Generate Resource
|
264
|
-
|
265
|
-
```
|
266
|
-
rails g model Event title:name start_date:date
|
267
|
-
bundle exec rake db:migrate
|
268
|
-
rails g decanter Event title:name start_date:date
|
269
|
-
rails g serializer Event title:name start_date:date
|
270
|
-
rails g actions Events
|
271
|
-
```
|
272
|
-
|
273
|
-
### 3. Add Routes
|
319
|
+
As you can see, we can abstract most of the `create` logic to be shared across resources, which means you **only need to write the code that is unique about this create action vs. other create actions**.
|
274
320
|
|
275
|
-
```ruby
|
276
|
-
Rails.application.routes.draw do
|
277
|
-
create_sweet_actions(:events)
|
278
|
-
end
|
279
|
-
```
|
@@ -1,10 +1,9 @@
|
|
1
|
-
class CollectAction < SweetActions::CollectAction
|
2
|
-
def set_resource
|
3
|
-
|
4
|
-
end
|
1
|
+
class CollectAction < SweetActions::JSON::CollectAction
|
2
|
+
# def set_resource
|
3
|
+
# resource_class.all
|
4
|
+
# end
|
5
5
|
|
6
|
-
def authorized?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
# def authorized?
|
7
|
+
# false
|
8
|
+
# end
|
10
9
|
end
|
@@ -1,14 +1,13 @@
|
|
1
|
-
class CreateAction < SweetActions::CreateAction
|
2
|
-
def set_resource
|
3
|
-
|
4
|
-
end
|
1
|
+
class CreateAction < SweetActions::JSON::CreateAction
|
2
|
+
# def set_resource
|
3
|
+
# resource_class.new(resource_params)
|
4
|
+
# end
|
5
5
|
|
6
|
-
def authorized?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
# def authorized?
|
7
|
+
# can?(:create, resource)
|
8
|
+
# end
|
10
9
|
|
11
|
-
def save
|
12
|
-
|
13
|
-
end
|
10
|
+
# def save
|
11
|
+
# resource.save
|
12
|
+
# end
|
14
13
|
end
|
@@ -1,14 +1,13 @@
|
|
1
|
-
class DestroyAction < SweetActions::DestroyAction
|
2
|
-
def set_resource
|
3
|
-
|
4
|
-
end
|
1
|
+
class DestroyAction < SweetActions::JSON::DestroyAction
|
2
|
+
# def set_resource
|
3
|
+
# resource_class.find(params[:id])
|
4
|
+
# end
|
5
5
|
|
6
|
-
def authorized?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
# def authorized?
|
7
|
+
# can?(:destroy, resource)
|
8
|
+
# end
|
10
9
|
|
11
|
-
def destroy
|
12
|
-
|
13
|
-
end
|
10
|
+
# def destroy
|
11
|
+
# resource.destroy
|
12
|
+
# end
|
14
13
|
end
|
@@ -1,10 +1,9 @@
|
|
1
|
-
class ShowAction < SweetActions::ShowAction
|
2
|
-
def set_resource
|
3
|
-
|
4
|
-
end
|
1
|
+
class ShowAction < SweetActions::JSON::ShowAction
|
2
|
+
# def set_resource
|
3
|
+
# resource_class.find(params[:id])
|
4
|
+
# end
|
5
5
|
|
6
|
-
def authorized?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
# def authorized?
|
7
|
+
# can?(:read, resource)
|
8
|
+
# end
|
10
9
|
end
|
@@ -1,15 +1,14 @@
|
|
1
|
-
class UpdateAction < SweetActions::UpdateAction
|
2
|
-
def set_resource
|
3
|
-
|
4
|
-
end
|
1
|
+
class UpdateAction < SweetActions::JSON::UpdateAction
|
2
|
+
# def set_resource
|
3
|
+
# resource_class.find(params[:id])
|
4
|
+
# end
|
5
5
|
|
6
|
-
def authorized?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
# def authorized?
|
7
|
+
# can?(:update, resource)
|
8
|
+
# end
|
10
9
|
|
11
|
-
def save
|
12
|
-
|
13
|
-
|
14
|
-
end
|
10
|
+
# def save
|
11
|
+
# resource.attributes = resource_params
|
12
|
+
# resource.save
|
13
|
+
# end
|
15
14
|
end
|
data/lib/sweet_actions/.DS_Store
CHANGED
Binary file
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module SweetActions
|
2
|
+
class Action
|
3
|
+
attr_reader :controller
|
4
|
+
|
5
|
+
def initialize(controller, options = {})
|
6
|
+
@controller = controller
|
7
|
+
after_init(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform_action
|
11
|
+
action
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
delegate :request, :params, to: :controller
|
17
|
+
|
18
|
+
def after_init(options); end
|
19
|
+
|
20
|
+
def action
|
21
|
+
raise "action method is required for #{self.class.name} because it inherits from SweetActions::Action"
|
22
|
+
end
|
23
|
+
|
24
|
+
def env
|
25
|
+
request.env
|
26
|
+
end
|
27
|
+
|
28
|
+
def path_parameters
|
29
|
+
@path_parameters ||= env['action_dispatch.request.path_parameters']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -21,9 +21,11 @@ module SweetActions
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def action_class
|
24
|
-
|
24
|
+
parts = [namespace, resource_module, action_class_name].compact
|
25
|
+
klass_name = parts.join('::')
|
25
26
|
return klass_name.constantize if klass_defined?(klass_name)
|
26
|
-
|
27
|
+
path = parts.map(&:downcase).join('/')
|
28
|
+
raise SweetActions::Exceptions::ActionNotFound, path: path, class_name: klass_name
|
27
29
|
end
|
28
30
|
|
29
31
|
def resource_module
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module SweetActions
|
2
|
-
module
|
2
|
+
module Authorization
|
3
3
|
private
|
4
4
|
|
5
5
|
def authorize?
|
@@ -13,7 +13,7 @@ module SweetActions
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def authorized?
|
16
|
-
|
16
|
+
false # lock it down by default
|
17
17
|
end
|
18
18
|
|
19
19
|
def unauthorized
|
@@ -1,5 +1,18 @@
|
|
1
1
|
module SweetActions
|
2
2
|
module Exceptions
|
3
3
|
class NotAuthorized < StandardError; end
|
4
|
+
|
5
|
+
class ActionNotFound < StandardError
|
6
|
+
attr_reader :path, :class_name
|
7
|
+
|
8
|
+
def initialize(args = {})
|
9
|
+
@path = args.fetch(:path, '')
|
10
|
+
@class_name = args.fetch(:class_name, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
"Action class not found. Please make sure #{class_name} exists at app/actions/#{path}."
|
15
|
+
end
|
16
|
+
end
|
4
17
|
end
|
5
18
|
end
|
Binary file
|