effective_resources 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +104 -2
- data/app/controllers/concerns/effective/crud_controller/permitted_params.rb +1 -1
- data/app/controllers/concerns/effective/crud_controller/submits.rb +4 -4
- data/app/helpers/effective_resources_helper.rb +1 -1
- data/app/helpers/effective_resources_private_helper.rb +3 -2
- data/app/models/concerns/acts_as_archived.rb +1 -1
- data/app/models/effective/resource_exec.rb +19 -0
- data/app/models/effective/resources/controller.rb +6 -6
- data/lib/effective_resources/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64dfc3d7de672e57ba2ea0238a214acc4cef4a5e
|
4
|
+
data.tar.gz: 5c6e8b73c793b0dbfb1e9b38353621bc67193324
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d737b31f4efc019d091a98712d3b4d56f6cd5a82ca18b59273ea838a1d4287f855294801b16351d7de54852d28cb383f9276ce16c721c9103df07477739158a
|
7
|
+
data.tar.gz: c07020c1c837060e43dfa69682da5a9027cd33113fc19d0af71bf86e82ec8ff601507433cd99b4e12921b1c4b21f5515a10ce8ec45ac5e0b2becca6c4a871d2a
|
data/README.md
CHANGED
@@ -1,8 +1,32 @@
|
|
1
1
|
# Effective Resources
|
2
2
|
|
3
|
-
|
3
|
+
The goal of this gem is to reduce the amount of code that needs to be written when developing a ruby on rails website.
|
4
|
+
|
5
|
+
It is ruby on rails, on effective rails.
|
6
|
+
|
7
|
+
A rails developer will always need to maintain and write:
|
8
|
+
|
9
|
+
- The `routes.rb` as it's the single most important file in an entire app.
|
10
|
+
- The `ability.rb` or other authorization.
|
11
|
+
- A normal active record model file for each model / form object / interaction / resource, whatever.
|
12
|
+
- A corresponding form.
|
13
|
+
- Any javascripts, etc, and unique resource actions.
|
14
|
+
|
15
|
+
However, all other patterns and a lot of code can be automated.
|
16
|
+
|
17
|
+
This gem replaces the following work a rails developer would normally do:
|
4
18
|
|
19
|
+
- Controllers.
|
20
|
+
- permitted params. This gem implements a model dsl to define and blacklist params. It's not the rails way.
|
21
|
+
|
22
|
+
- Any file named index/edit/show/new.html. We use rails application templates and powerful defaults views so these files need never be written.
|
23
|
+
- Figure out actions available to the `current_user` to each `resource` on the fly, based on controller namespace, the routes.rb and ability.rb
|
24
|
+
- Powerful helpers to render the correct resource action links.
|
25
|
+
- Collection of concern files.
|
26
|
+
|
27
|
+
Make your controller an effective resource controller.
|
5
28
|
Implements the 7 RESTful actions as a one-liner on any controller.
|
29
|
+
Reads the `routes.rb` and serves collection and member actions.
|
6
30
|
|
7
31
|
## Getting Started
|
8
32
|
|
@@ -26,6 +50,45 @@ The generator will install an initializer which describes all configuration opti
|
|
26
50
|
|
27
51
|
## Usage
|
28
52
|
|
53
|
+
Add to your `app/models/post.rb`:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class Post < ApplicationRecord
|
57
|
+
belongs_to :author, class_name: 'User'
|
58
|
+
|
59
|
+
# The only thing this block is used for - right now - is permitted_params
|
60
|
+
# So yo
|
61
|
+
effective_resource do
|
62
|
+
category :string
|
63
|
+
title :string
|
64
|
+
body :text
|
65
|
+
|
66
|
+
approved :boolean, permitted: false # You could write permitted: [:admin] to only permit this in the admin namespace
|
67
|
+
|
68
|
+
timestamps
|
69
|
+
end
|
70
|
+
|
71
|
+
# The approve! action will be called by Effective::CrudController when submitted on a create/update or member action
|
72
|
+
def approve!
|
73
|
+
raise 'already approved' if approved?
|
74
|
+
update!(approved: true)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
Add to your `routes.rb`:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
resources :posts, only: [:index, :show] do
|
84
|
+
get :approve, on: :member
|
85
|
+
post :approve, on: :member
|
86
|
+
|
87
|
+
get :approved, on: :collection
|
88
|
+
post :bulk_approve, on: :collection
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
29
92
|
Add to your contoller:
|
30
93
|
|
31
94
|
```ruby
|
@@ -43,6 +106,9 @@ class PostsController < ApplicationController
|
|
43
106
|
Post.active.where(user: current_user)
|
44
107
|
end
|
45
108
|
|
109
|
+
# The following methods are discovered from the routes.rb and defined automatically.
|
110
|
+
# But you could also define them like this if you wanted.
|
111
|
+
|
46
112
|
# When GET request, will render the approve page
|
47
113
|
# When POST|PATCH|PUT request, will call @post.approve! and do the right thing
|
48
114
|
member_action :approve
|
@@ -56,7 +122,9 @@ class PostsController < ApplicationController
|
|
56
122
|
|
57
123
|
protected
|
58
124
|
|
59
|
-
# The
|
125
|
+
# The post_params are discovered from the model effective_resource do ... end block.
|
126
|
+
# But you could also define them like this if you wanted.
|
127
|
+
# Other recognized method names are posts_params and permitted_params
|
60
128
|
def post_params
|
61
129
|
params.require(:post).permit(:id, :author_id, :category, :title, :body)
|
62
130
|
end
|
@@ -190,6 +258,40 @@ This prevents enumeration of this resource.
|
|
190
258
|
|
191
259
|
Make sure to create a string `token` field on your model, then just declare `acts_as_tokened`. There are no options.
|
192
260
|
|
261
|
+
### acts_as_archived
|
262
|
+
|
263
|
+
Create an 'archived' boolean filed in your model, then declare `acts_as_archived`.
|
264
|
+
|
265
|
+
Implements the dumb archived pattern.
|
266
|
+
|
267
|
+
An archived object should not be displayed on index screens, or any related resource's #new pages
|
268
|
+
|
269
|
+
effective_select (from the effective_bootstrap gem) is aware of this concern, and calls `.unarchived` and `.archived` appropriately when passed an ActiveRecord relation.
|
270
|
+
|
271
|
+
Use the cascade argument to cascade archived changes to any has_manys
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
class Thing < ApplicationRecord
|
275
|
+
has_many :comments
|
276
|
+
acts_as_archivable cascade: :comments
|
277
|
+
end
|
278
|
+
```
|
279
|
+
|
280
|
+
Each controller needs its own archive and unarchive action.
|
281
|
+
To simplify this, use the following route concern.
|
282
|
+
|
283
|
+
In your routes.rb:
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
Rails.application.routes.draw do
|
287
|
+
acts_as_archived
|
288
|
+
|
289
|
+
resource :things, concern: :acts_as_archived
|
290
|
+
resource :comments, concern: :acts_as_archived
|
291
|
+
end
|
292
|
+
```
|
293
|
+
|
294
|
+
and include Effective::CrudController in your resource controller.
|
193
295
|
|
194
296
|
## License
|
195
297
|
|
@@ -53,7 +53,7 @@ module Effective
|
|
53
53
|
elsif atts.blank? || !atts.key?(:permitted)
|
54
54
|
true # Default is true
|
55
55
|
else
|
56
|
-
permitted = (atts[:permitted].respond_to?(:call) ? instance_exec(&atts[:permitted]) : atts[:permitted])
|
56
|
+
permitted = (atts[:permitted].respond_to?(:call) ? Effective::ResourceExec.new(self, resource).instance_exec(&atts[:permitted]) : atts[:permitted])
|
57
57
|
|
58
58
|
if permitted == true || permitted == false
|
59
59
|
permitted
|
@@ -36,11 +36,11 @@ module Effective
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if args.key?(:if) && args[:if].respond_to?(:call) == false
|
39
|
-
raise "expected if: to be callable. Try submit :approve, 'Save and Approve', if: ->
|
39
|
+
raise "expected if: to be callable. Try submit :approve, 'Save and Approve', if: -> { resource.finished? }"
|
40
40
|
end
|
41
41
|
|
42
42
|
if args.key?(:unless) && args[:unless].respond_to?(:call) == false
|
43
|
-
raise "expected unless: to be callable. Try submit :approve, 'Save and Approve', unless: ->
|
43
|
+
raise "expected unless: to be callable. Try submit :approve, 'Save and Approve', unless: -> { resource.declined? }"
|
44
44
|
end
|
45
45
|
|
46
46
|
if args.key?(:only)
|
@@ -78,11 +78,11 @@ module Effective
|
|
78
78
|
end
|
79
79
|
|
80
80
|
if args.key?(:if) && args[:if].respond_to?(:call) == false
|
81
|
-
raise "expected if: to be callable. Try button :approve, 'Approve', if: ->
|
81
|
+
raise "expected if: to be callable. Try button :approve, 'Approve', if: -> { resource.finished? }"
|
82
82
|
end
|
83
83
|
|
84
84
|
if args.key?(:unless) && args[:unless].respond_to?(:call) == false
|
85
|
-
raise "expected unless: to be callable. Try button :approve, 'Approve', unless: ->
|
85
|
+
raise "expected unless: to be callable. Try button :approve, 'Approve', unless: -> { resource.declined? }"
|
86
86
|
end
|
87
87
|
|
88
88
|
if args.key?(:only)
|
@@ -77,7 +77,7 @@ module EffectiveResourcesHelper
|
|
77
77
|
end
|
78
78
|
|
79
79
|
# Filter out false and proc false
|
80
|
-
actions = actions.select { |_, v| atts[v[:action]].respond_to?(:call) ? instance_exec(&atts[v[:action]]) : (atts[v[:action]] != false) }
|
80
|
+
actions = actions.select { |_, v| atts[v[:action]].respond_to?(:call) ? Effective::ResourceExec.new(self, resource).instance_exec(&atts[v[:action]]) : (atts[v[:action]] != false) }
|
81
81
|
|
82
82
|
# Select Partial
|
83
83
|
partial = ['effective/resource/actions', partial.to_s].join('_') if partial.kind_of?(Symbol)
|
@@ -5,14 +5,15 @@ module EffectiveResourcesPrivateHelper
|
|
5
5
|
|
6
6
|
def permitted_resource_actions(resource, actions)
|
7
7
|
page_action = REPLACE_PAGE_ACTIONS[params[:action]] || params[:action]&.to_sym || :save
|
8
|
+
executor = Effective::ResourceExec.new(self, resource)
|
8
9
|
|
9
10
|
actions.select do |commit, args|
|
10
11
|
action = (args[:action] == :save ? (resource.new_record? ? :create : :update) : args[:action])
|
11
12
|
|
12
13
|
(args.key?(:only) ? args[:only].include?(page_action) : true) &&
|
13
14
|
(args.key?(:except) ? !args[:except].include?(page_action) : true) &&
|
14
|
-
(args.key?(:if) ?
|
15
|
-
(args.key?(:unless) ? !
|
15
|
+
(args.key?(:if) ? executor.instance_exec(&args[:if]) : true) &&
|
16
|
+
(args.key?(:unless) ? !executor.instance_exec(&args[:unless]) : true) &&
|
16
17
|
EffectiveResources.authorized?(controller, action, resource)
|
17
18
|
end.inject({}) do |h, (commit, args)|
|
18
19
|
opts = args.except(:default, :only, :except, :if, :unless, :redirect, :success, :danger)
|
@@ -44,7 +44,7 @@ module ActsAsArchived
|
|
44
44
|
|
45
45
|
module CanCan
|
46
46
|
def acts_as_archived(klass)
|
47
|
-
raise "klass does not implement acts_as_archived" unless klass.acts_as_archived?
|
47
|
+
raise "klass does not implement acts_as_archived" unless klass.respond_to?(:acts_as_archived?)
|
48
48
|
|
49
49
|
can(:archive, klass) { |obj| !obj.archived? }
|
50
50
|
can(:unarchive, klass) { |obj| obj.archived? }
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Makes sure resource in any instance_execs is the correct resource
|
2
|
+
module Effective
|
3
|
+
class ResourceExec
|
4
|
+
|
5
|
+
def initialize(instance, resource)
|
6
|
+
@instance = instance
|
7
|
+
@resource = resource
|
8
|
+
end
|
9
|
+
|
10
|
+
def resource
|
11
|
+
@resource
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method, *args, &block)
|
15
|
+
@instance.send(method, *args)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -13,11 +13,11 @@ module Effective
|
|
13
13
|
end
|
14
14
|
|
15
15
|
if actions.find { |a| a == :index }
|
16
|
-
submits['Continue'] = { action: :save, redirect: :index, default: true, unless: ->
|
16
|
+
submits['Continue'] = { action: :save, redirect: :index, default: true, unless: -> { params[:_datatable_id].present? } }
|
17
17
|
end
|
18
18
|
|
19
19
|
if actions.find { |a| a == :new }
|
20
|
-
submits['Add New'] = { action: :save, redirect: :new, default: true, unless: ->
|
20
|
+
submits['Add New'] = { action: :save, redirect: :new, default: true, unless: -> { params[:_datatable_id].present? } }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -31,9 +31,9 @@ module Effective
|
|
31
31
|
(member_post_actions - crud_actions).each do |action| # default true means it will be overwritten by dsl methods
|
32
32
|
buttons[action.to_s.titleize] = case action
|
33
33
|
when :archive
|
34
|
-
{ action: action, default: true, if: ->
|
34
|
+
{ action: action, default: true, if: -> { !resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
|
35
35
|
when :unarchive
|
36
|
-
{ action: action, default: true, if: ->
|
36
|
+
{ action: action, default: true, if: -> { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
|
37
37
|
else
|
38
38
|
{ action: action, default: true, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
|
39
39
|
end
|
@@ -79,9 +79,9 @@ module Effective
|
|
79
79
|
|
80
80
|
actions[action.to_s.titleize] = case action
|
81
81
|
when :archive
|
82
|
-
{ action: action, default: true, if: ->
|
82
|
+
{ action: action, default: true, if: -> { resource.archived? }, class: 'btn btn-danger', 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?"}
|
83
83
|
when :unarchive
|
84
|
-
{ action: action, default: true, if: ->
|
84
|
+
{ action: action, default: true, if: -> { resource.archived? }, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
|
85
85
|
else
|
86
86
|
{ action: action, default: true, 'data-method' => :post, 'data-confirm' => "Really #{action} @resource?" }
|
87
87
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- app/models/effective/code_reader.rb
|
58
58
|
- app/models/effective/model_reader.rb
|
59
59
|
- app/models/effective/resource.rb
|
60
|
+
- app/models/effective/resource_exec.rb
|
60
61
|
- app/models/effective/resources/actions.rb
|
61
62
|
- app/models/effective/resources/associations.rb
|
62
63
|
- app/models/effective/resources/attributes.rb
|