effective_resources 1.2.2 → 1.2.3
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 +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
|