active_manageable 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +55 -55
- data/README.md +82 -12
- data/lib/active_manageable/authorization/cancancan.rb +10 -12
- data/lib/active_manageable/authorization/pundit.rb +10 -12
- data/lib/active_manageable/base.rb +14 -3
- data/lib/active_manageable/configuration.rb +16 -7
- data/lib/active_manageable/methods/auxiliary/includes.rb +28 -30
- data/lib/active_manageable/methods/auxiliary/model_attributes.rb +15 -17
- data/lib/active_manageable/methods/auxiliary/order.rb +12 -14
- data/lib/active_manageable/methods/auxiliary/scopes.rb +35 -28
- data/lib/active_manageable/methods/auxiliary/select.rb +11 -13
- data/lib/active_manageable/methods/auxiliary/unique_search.rb +19 -19
- data/lib/active_manageable/methods/create.rb +20 -5
- data/lib/active_manageable/methods/destroy.rb +22 -7
- data/lib/active_manageable/methods/edit.rb +17 -9
- data/lib/active_manageable/methods/index.rb +28 -26
- data/lib/active_manageable/methods/new.rb +14 -6
- data/lib/active_manageable/methods/show.rb +17 -9
- data/lib/active_manageable/methods/update.rb +28 -7
- data/lib/active_manageable/pagination/kaminari.rb +29 -9
- data/lib/active_manageable/search/ransack.rb +15 -17
- data/lib/active_manageable/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33e6916eea9e70cfa5c04813328b8e1cb21e93f3f2638705b2ec0b37748de51c
|
4
|
+
data.tar.gz: 37122950ad83b210bd043ce2fc556032451df60deef18dc4f58cead9917f1f1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2afeaad9032f497b31208e0e4c8b21e209b40d81346dc1468a3eefdb251e1d6c5c01f6759d58e2cab99782116920845077fd62bcb90a54e20ac7c322c556647
|
7
|
+
data.tar.gz: 608affa3ab36c003c03c0af6f27d09b404cfd6e8b987bd6ec57b3605b7f93910b95409073afda386f1e4fb33998cb07bdcc1428ddcf23ae3bac5eb2e2b0eefb7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.2.0 - 2022-09-27
|
4
|
+
|
5
|
+
* Allow the configuration library options to accept a module
|
6
|
+
* Add `action_scope` method that can be overridden in order to retrieve and maintain records using a scope
|
7
|
+
* Rename `scoped_class` method to `authorization_scope`
|
8
|
+
* Move instance method definitions out of the ActiveSupport::Concern included block so that they can be overridden
|
9
|
+
* Split action methods into smaller overridable methods
|
10
|
+
* Add a yield to each of the action methods
|
11
|
+
* Perform yield and object create, update & destroy within a transaction
|
12
|
+
* Add public instance methods to return the default options
|
13
|
+
* When using the Kaminari library provide the ability to use the `without_count` mode to create a paginatable collection without counting the total number of records; either via the index method options or a class option or configuration option
|
14
|
+
|
15
|
+
## 0.1.2 - 2022-08-25
|
16
|
+
|
17
|
+
* Upgrade gems including activerecord, actionpack, actionview, nokogiri & rack to resolve security advisory alerts
|
18
|
+
|
3
19
|
## 0.1.1 - 2022-04-18
|
4
20
|
|
5
21
|
* Upgrade nokogiri to v1.13.4 to resolve security advisory
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active_manageable (0.
|
4
|
+
active_manageable (0.2.0)
|
5
5
|
activerecord (>= 6.0)
|
6
6
|
activesupport (>= 6.0)
|
7
7
|
flexitime (~> 1.0)
|
@@ -10,25 +10,25 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
actionpack (7.0.
|
14
|
-
actionview (= 7.0.
|
15
|
-
activesupport (= 7.0.
|
13
|
+
actionpack (7.0.3.1)
|
14
|
+
actionview (= 7.0.3.1)
|
15
|
+
activesupport (= 7.0.3.1)
|
16
16
|
rack (~> 2.0, >= 2.2.0)
|
17
17
|
rack-test (>= 0.6.3)
|
18
18
|
rails-dom-testing (~> 2.0)
|
19
19
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
20
|
-
actionview (7.0.
|
21
|
-
activesupport (= 7.0.
|
20
|
+
actionview (7.0.3.1)
|
21
|
+
activesupport (= 7.0.3.1)
|
22
22
|
builder (~> 3.1)
|
23
23
|
erubi (~> 1.4)
|
24
24
|
rails-dom-testing (~> 2.0)
|
25
25
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
26
|
-
activemodel (7.0.
|
27
|
-
activesupport (= 7.0.
|
28
|
-
activerecord (7.0.
|
29
|
-
activemodel (= 7.0.
|
30
|
-
activesupport (= 7.0.
|
31
|
-
activesupport (7.0.
|
26
|
+
activemodel (7.0.3.1)
|
27
|
+
activesupport (= 7.0.3.1)
|
28
|
+
activerecord (7.0.3.1)
|
29
|
+
activemodel (= 7.0.3.1)
|
30
|
+
activesupport (= 7.0.3.1)
|
31
|
+
activesupport (7.0.3.1)
|
32
32
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
33
33
|
i18n (>= 1.6, < 2)
|
34
34
|
minitest (>= 5.1)
|
@@ -39,20 +39,20 @@ GEM
|
|
39
39
|
thor (>= 0.14.0)
|
40
40
|
ast (2.4.2)
|
41
41
|
builder (3.2.4)
|
42
|
-
cancancan (3.
|
43
|
-
concurrent-ruby (1.1.
|
42
|
+
cancancan (3.4.0)
|
43
|
+
concurrent-ruby (1.1.10)
|
44
44
|
crass (1.0.6)
|
45
45
|
diff-lcs (1.5.0)
|
46
46
|
docile (1.4.0)
|
47
|
-
erubi (1.
|
48
|
-
factory_bot (6.2.
|
47
|
+
erubi (1.11.0)
|
48
|
+
factory_bot (6.2.1)
|
49
49
|
activesupport (>= 5.0.0)
|
50
50
|
factory_bot_rails (6.2.0)
|
51
51
|
factory_bot (~> 6.2.0)
|
52
52
|
railties (>= 5.0.0)
|
53
53
|
flexitime (1.0.0)
|
54
54
|
activesupport (>= 4.0)
|
55
|
-
i18n (1.
|
55
|
+
i18n (1.12.0)
|
56
56
|
concurrent-ruby (~> 1.0)
|
57
57
|
kaminari (1.2.2)
|
58
58
|
activesupport (>= 4.1.0)
|
@@ -66,24 +66,24 @@ GEM
|
|
66
66
|
activerecord
|
67
67
|
kaminari-core (= 1.2.2)
|
68
68
|
kaminari-core (1.2.2)
|
69
|
-
loofah (2.
|
69
|
+
loofah (2.18.0)
|
70
70
|
crass (~> 1.0.2)
|
71
71
|
nokogiri (>= 1.5.9)
|
72
72
|
method_source (1.0.0)
|
73
|
-
minitest (5.
|
74
|
-
nokogiri (1.13.
|
73
|
+
minitest (5.16.3)
|
74
|
+
nokogiri (1.13.8-arm64-darwin)
|
75
75
|
racc (~> 1.4)
|
76
|
-
nokogiri (1.13.
|
76
|
+
nokogiri (1.13.8-x86_64-linux)
|
77
77
|
racc (~> 1.4)
|
78
|
-
parallel (1.
|
79
|
-
parser (3.
|
78
|
+
parallel (1.22.1)
|
79
|
+
parser (3.1.2.1)
|
80
80
|
ast (~> 2.4.1)
|
81
|
-
pundit (2.
|
81
|
+
pundit (2.2.0)
|
82
82
|
activesupport (>= 3.0.0)
|
83
83
|
racc (1.6.0)
|
84
|
-
rack (2.2.
|
85
|
-
rack-test (
|
86
|
-
rack (>= 1.
|
84
|
+
rack (2.2.4)
|
85
|
+
rack-test (2.0.2)
|
86
|
+
rack (>= 1.3)
|
87
87
|
rails-controller-testing (1.0.5)
|
88
88
|
actionpack (>= 5.0.1.rc1)
|
89
89
|
actionview (>= 5.0.1.rc1)
|
@@ -91,35 +91,35 @@ GEM
|
|
91
91
|
rails-dom-testing (2.0.3)
|
92
92
|
activesupport (>= 4.2.0)
|
93
93
|
nokogiri (>= 1.6)
|
94
|
-
rails-html-sanitizer (1.4.
|
94
|
+
rails-html-sanitizer (1.4.3)
|
95
95
|
loofah (~> 2.3)
|
96
|
-
rails-i18n (7.0.
|
96
|
+
rails-i18n (7.0.5)
|
97
97
|
i18n (>= 0.7, < 2)
|
98
98
|
railties (>= 6.0.0, < 8)
|
99
|
-
railties (7.0.
|
100
|
-
actionpack (= 7.0.
|
101
|
-
activesupport (= 7.0.
|
99
|
+
railties (7.0.3.1)
|
100
|
+
actionpack (= 7.0.3.1)
|
101
|
+
activesupport (= 7.0.3.1)
|
102
102
|
method_source
|
103
103
|
rake (>= 12.2)
|
104
104
|
thor (~> 1.0)
|
105
105
|
zeitwerk (~> 2.5)
|
106
|
-
rainbow (3.
|
106
|
+
rainbow (3.1.1)
|
107
107
|
rake (13.0.6)
|
108
|
-
ransack (2.
|
109
|
-
activerecord (>=
|
110
|
-
activesupport (>=
|
108
|
+
ransack (3.2.1)
|
109
|
+
activerecord (>= 6.1.5)
|
110
|
+
activesupport (>= 6.1.5)
|
111
111
|
i18n
|
112
|
-
regexp_parser (2.
|
112
|
+
regexp_parser (2.5.0)
|
113
113
|
rexml (3.2.5)
|
114
|
-
rspec-core (3.
|
115
|
-
rspec-support (~> 3.
|
116
|
-
rspec-expectations (3.
|
114
|
+
rspec-core (3.11.0)
|
115
|
+
rspec-support (~> 3.11.0)
|
116
|
+
rspec-expectations (3.11.0)
|
117
117
|
diff-lcs (>= 1.2.0, < 2.0)
|
118
|
-
rspec-support (~> 3.
|
119
|
-
rspec-mocks (3.
|
118
|
+
rspec-support (~> 3.11.0)
|
119
|
+
rspec-mocks (3.11.1)
|
120
120
|
diff-lcs (>= 1.2.0, < 2.0)
|
121
|
-
rspec-support (~> 3.
|
122
|
-
rspec-rails (5.
|
121
|
+
rspec-support (~> 3.11.0)
|
122
|
+
rspec-rails (5.1.2)
|
123
123
|
actionpack (>= 5.2)
|
124
124
|
activesupport (>= 5.2)
|
125
125
|
railties (>= 5.2)
|
@@ -127,7 +127,7 @@ GEM
|
|
127
127
|
rspec-expectations (~> 3.10)
|
128
128
|
rspec-mocks (~> 3.10)
|
129
129
|
rspec-support (~> 3.10)
|
130
|
-
rspec-support (3.
|
130
|
+
rspec-support (3.11.0)
|
131
131
|
rubocop (1.23.0)
|
132
132
|
parallel (~> 1.10)
|
133
133
|
parser (>= 3.0.0.0)
|
@@ -137,16 +137,16 @@ GEM
|
|
137
137
|
rubocop-ast (>= 1.12.0, < 2.0)
|
138
138
|
ruby-progressbar (~> 1.7)
|
139
139
|
unicode-display_width (>= 1.4.0, < 3.0)
|
140
|
-
rubocop-ast (1.
|
141
|
-
parser (>= 3.
|
140
|
+
rubocop-ast (1.21.0)
|
141
|
+
parser (>= 3.1.1.0)
|
142
142
|
rubocop-performance (1.12.0)
|
143
143
|
rubocop (>= 1.7.0, < 2.0)
|
144
144
|
rubocop-ast (>= 0.4.0)
|
145
|
-
rubocop-rails (2.
|
145
|
+
rubocop-rails (2.15.2)
|
146
146
|
activesupport (>= 4.2.0)
|
147
147
|
rack (>= 1.1)
|
148
148
|
rubocop (>= 1.7.0, < 2.0)
|
149
|
-
rubocop-rspec (2.
|
149
|
+
rubocop-rspec (2.11.1)
|
150
150
|
rubocop (~> 1.19)
|
151
151
|
ruby-progressbar (1.11.0)
|
152
152
|
shoulda-matchers (5.1.0)
|
@@ -156,16 +156,16 @@ GEM
|
|
156
156
|
simplecov-html (~> 0.11)
|
157
157
|
simplecov_json_formatter (~> 0.1)
|
158
158
|
simplecov-html (0.12.3)
|
159
|
-
simplecov_json_formatter (0.1.
|
160
|
-
sqlite3 (1.4.
|
159
|
+
simplecov_json_formatter (0.1.4)
|
160
|
+
sqlite3 (1.4.4)
|
161
161
|
standard (1.5.0)
|
162
162
|
rubocop (= 1.23.0)
|
163
163
|
rubocop-performance (= 1.12.0)
|
164
|
-
thor (1.1
|
165
|
-
tzinfo (2.0.
|
164
|
+
thor (1.2.1)
|
165
|
+
tzinfo (2.0.5)
|
166
166
|
concurrent-ruby (~> 1.0)
|
167
|
-
unicode-display_width (2.
|
168
|
-
zeitwerk (2.
|
167
|
+
unicode-display_width (2.2.0)
|
168
|
+
zeitwerk (2.6.0)
|
169
169
|
|
170
170
|
PLATFORMS
|
171
171
|
arm64-darwin-21
|
data/README.md
CHANGED
@@ -49,7 +49,7 @@ def index
|
|
49
49
|
end
|
50
50
|
```
|
51
51
|
|
52
|
-
The manager classes provide standard implementations of the seven core CRUD methods. These can be overwritten to perform custom business logic and the classes can also be extended to include the business logic for additional actions, both making use of the internal ActiveManageable methods and variables described in the [Adding Bespoke Methods](#adding-bespoke-methods) section.
|
52
|
+
The manager classes provide standard implementations of the seven core CRUD methods. These can be extended or overwritten to perform custom business logic and the classes can also be extended to include the business logic for additional actions, both making use of the internal ActiveManageable methods and variables described in the [Adding Bespoke Methods](#adding-bespoke-methods) section.
|
53
53
|
|
54
54
|
With an Activity model in a CRM application to manage meetings & tasks, a complete action may be required. This could be implemented as follows:
|
55
55
|
|
@@ -110,6 +110,7 @@ gem install active_manageable
|
|
110
110
|
- [Default Scopes](#default-scopes)
|
111
111
|
- [Unique Search](#unique-search)
|
112
112
|
- [Default Page Size](#default-page-size)
|
113
|
+
- [Paginate Without Count](#paginate-without-count)
|
113
114
|
- [Current Method](#current-method)
|
114
115
|
- [Index Method](#index-method)
|
115
116
|
- [Authorization Scope](#index-authorization-scope)
|
@@ -131,6 +132,8 @@ gem install active_manageable
|
|
131
132
|
- [Includes Option](#update-includes-option)
|
132
133
|
- [Destroy Method](#destroy-method)
|
133
134
|
- [Includes Option](#destroy-includes-option)
|
135
|
+
- [Extending the CRUD Methods](#extending-the-crud-methods)
|
136
|
+
- [Build and Retrieve Scoped Records](#build-and-retrieve-scoped-records)
|
134
137
|
- [Attribute Value Parsing](#attribute-value-parsing)
|
135
138
|
- [Date and DateTime Attribute Values](#date-and-datetime-attribute-values)
|
136
139
|
- [Numeric Attribute Values](#numeric-attribute-values)
|
@@ -143,7 +146,7 @@ gem install active_manageable
|
|
143
146
|
|
144
147
|
## Configuration
|
145
148
|
|
146
|
-
Create an initializer to configure the optional authorization, search and pagination libraries to use.
|
149
|
+
Create an initializer to configure the optional in-built authorization, search and pagination libraries to use.
|
147
150
|
|
148
151
|
```ruby
|
149
152
|
ActiveManageable.config do |config|
|
@@ -153,6 +156,8 @@ ActiveManageable.config do |config|
|
|
153
156
|
end
|
154
157
|
```
|
155
158
|
|
159
|
+
These library configuration options can also be set to a module in order to use a custom authorization, search or pagination implementation.
|
160
|
+
|
156
161
|
When eager loading associations the `includes` method is used by default but this can be changed via a configuration option that accepts `:includes`, `:preload` or `:eager_load`
|
157
162
|
|
158
163
|
```ruby
|
@@ -388,6 +393,31 @@ class AlbumManager < ActiveManageable::Base
|
|
388
393
|
end
|
389
394
|
```
|
390
395
|
|
396
|
+
### Paginate Without Count
|
397
|
+
|
398
|
+
When using the [Kaminari](https://github.com/kaminari/kaminari) pagination library, the `paginate_without_count` method will result in the index method using the Kaminari `without_count` mode to create a paginatable collection without counting the total number of records.
|
399
|
+
|
400
|
+
```ruby
|
401
|
+
class AlbumManager < ActiveManageable::Base
|
402
|
+
manageable :index
|
403
|
+
paginate_without_count
|
404
|
+
end
|
405
|
+
```
|
406
|
+
|
407
|
+
It is also possible to control whether to use the `without_count` mode globally by setting the `paginate_without_count` configuration option.
|
408
|
+
|
409
|
+
```ruby
|
410
|
+
ActiveManageable.config do |config|
|
411
|
+
config.paginate_without_count = true
|
412
|
+
end
|
413
|
+
```
|
414
|
+
|
415
|
+
And it is also possible to control whether to use the `without_count` mode for an individual index method call by including the `:without_count` key within the `options` argument `:page` hash.
|
416
|
+
|
417
|
+
```ruby
|
418
|
+
manager.index(options: {page: {number: 2, size: 10, without_count: true}})
|
419
|
+
```
|
420
|
+
|
391
421
|
### Current Method
|
392
422
|
|
393
423
|
ActiveManageable includes a `current_method` attribute which returns the name of the method being executed as a symbol, which can potentially be used within methods in conjunction with a lambda for the default methods described above. Additionally, the method argument `options` and `attributes` are also accessible as attributes.
|
@@ -411,7 +441,7 @@ end
|
|
411
441
|
|
412
442
|
## Index Method
|
413
443
|
|
414
|
-
The `index` method has an optional `options` keyword argument. The `options` hash can contain `:search`, `:order`, `:scopes`, `:page`, `:includes` and `:select` keys. The method performs authorization for the current user, method and model class using the configuration library; retrieves
|
444
|
+
The `index` method has an optional `options` keyword argument. The `options` hash can contain `:search`, `:order`, `:scopes`, `:page`, `:includes` and `:select` keys. The method performs authorization for the current user, method and model class using the configuration library; invokes a block (if provided); retrieves records using the various options described below; and returns the records which are also accessible via the `collection` attribute.
|
415
445
|
|
416
446
|
```ruby
|
417
447
|
manager.index
|
@@ -490,7 +520,7 @@ If the class `has_unique_search` method has been used then this will be evaluate
|
|
490
520
|
|
491
521
|
## Show Method
|
492
522
|
|
493
|
-
The `show` method has `id` and optional `options` keyword arguments. The `options` hash can contain `:includes` and `:select` keys. The method retrieves a record; performs authorization for the current user, method and record using the configuration library; and returns the record which is also accessible via the `object` attribute.
|
523
|
+
The `show` method has `id` and optional `options` keyword arguments. The `options` hash can contain `:includes` and `:select` keys. The method invokes a block (if provided); retrieves a record; performs authorization for the current user, method and record using the configuration library; and returns the record which is also accessible via the `object` attribute.
|
494
524
|
|
495
525
|
```ruby
|
496
526
|
manager.show(id: 1)
|
@@ -520,7 +550,7 @@ manager.show(id: 1, options: {select: [:id, :name, :artist_id, :released_at]})
|
|
520
550
|
|
521
551
|
## New Method
|
522
552
|
|
523
|
-
The `new` method has an optional `attributes` keyword argument. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when building the record. The method builds a record; performs authorization for the current user, method and record using the configuration library; and returns the record which is also accessible via the `object` attribute.
|
553
|
+
The `new` method has an optional `attributes` keyword argument. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when building the record. The method builds a record; performs authorization for the current user, method and record using the configuration library; invokes a block (if provided); and returns the record which is also accessible via the `object` attribute.
|
524
554
|
|
525
555
|
```ruby
|
526
556
|
manager.new
|
@@ -534,7 +564,7 @@ manager.new(attributes: {genre: "electronic", published_at: Date.current})
|
|
534
564
|
|
535
565
|
## Create Method
|
536
566
|
|
537
|
-
The `create` method has an `attributes` keyword argument. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when building the record. The method builds a record; performs authorization for the current user, method and record using the configuration library; attempts to save the record and returns the save result. The record is also accessible via the `object` attribute.
|
567
|
+
The `create` method has an `attributes` keyword argument. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when building the record. The method builds a record; performs authorization for the current user, method and record using the configuration library; invokes a block (if provided) and attempts to save the record within a transaction; and returns the save result. The record is also accessible via the `object` attribute.
|
538
568
|
|
539
569
|
```ruby
|
540
570
|
manager.create(attributes: {name: "Substance", genre: "electronic", published_at: Date.current})
|
@@ -544,7 +574,7 @@ The `attributes` argument values are combined with the class default values and
|
|
544
574
|
|
545
575
|
## Edit Method
|
546
576
|
|
547
|
-
The `edit` method has `id` and optional `options` keyword arguments. The `options` hash can contain `:includes` and `:select` keys. The method retrieves a record; performs authorization for the current user, method and record using the configuration library; and returns the record which is also accessible via the `object` attribute.
|
577
|
+
The `edit` method has `id` and optional `options` keyword arguments. The `options` hash can contain `:includes` and `:select` keys. The method invokes a block (if provided); retrieves a record; performs authorization for the current user, method and record using the configuration library; and returns the record which is also accessible via the `object` attribute.
|
548
578
|
|
549
579
|
```ruby
|
550
580
|
manager.edit(id: 1)
|
@@ -566,7 +596,7 @@ manager.edit(id: 1, options: {includes: {associations: :songs, loading_method: :
|
|
566
596
|
|
567
597
|
## Update Method
|
568
598
|
|
569
|
-
The `update` method has `id`, `attributes` and optional `options` keyword arguments. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when updating the record. The `options` hash can contain an `:includes` key. The method retrieves a record; performs authorization for the current user, method and record using the configuration library;
|
599
|
+
The `update` method has `id`, `attributes` and optional `options` keyword arguments. The `attributes` argument is for an `ActionController::Parameters` or hash of attribute names and values to use when updating the record. The `options` hash can contain an `:includes` key. The method retrieves a record; performs authorization for the current user, method and record using the configuration library; assigns the attributes; invokes a block (if provided) and attempts to save the record within a transaction; and returns the save result. The record is also accessible via the `object` attribute.
|
570
600
|
|
571
601
|
```ruby
|
572
602
|
manager.update(id: 1, attributes: {genre: "electronic", published_at: Date.current})
|
@@ -588,7 +618,7 @@ manager.update(id: 1, attributes: {published_at: Date.current}, options: {includ
|
|
588
618
|
|
589
619
|
## Destroy Method
|
590
620
|
|
591
|
-
The `destroy` method has `id` and optional `options` keyword arguments. The `options` hash can contain an `:includes` key. The method retrieves a record; performs authorization for the current user, method and record using the configuration library; attempts to destroy the record and returns the destroy result. The record is accessible via the `object` attribute.
|
621
|
+
The `destroy` method has `id` and optional `options` keyword arguments. The `options` hash can contain an `:includes` key. The method retrieves a record; performs authorization for the current user, method and record using the configuration library; invokes a block (if provided) and attempts to destroy the record within a transaction; and returns the destroy result. The record is accessible via the `object` attribute.
|
592
622
|
|
593
623
|
```ruby
|
594
624
|
manager.destroy(id: 1)
|
@@ -608,6 +638,37 @@ The `:includes` key can also be used to vary the method used to eager load assoc
|
|
608
638
|
manager.destroy(id: 1, options: {includes: {associations: :songs, loading_method: :preload}})
|
609
639
|
```
|
610
640
|
|
641
|
+
## Extending the CRUD Methods
|
642
|
+
|
643
|
+
Each of the seven core CRUD methods include a `yield` so it is possible to extend the methods by passing a block.
|
644
|
+
|
645
|
+
```ruby
|
646
|
+
def create(attributes:)
|
647
|
+
super do
|
648
|
+
@target.description = "change the object before it is created using a block"
|
649
|
+
end
|
650
|
+
end
|
651
|
+
```
|
652
|
+
|
653
|
+
The logic within each of the methods has also been split into subsidiary methods so it is possible to extend or override these methods.
|
654
|
+
|
655
|
+
```ruby
|
656
|
+
def create_object
|
657
|
+
@target.description = "change the object before it is created via an override"
|
658
|
+
super
|
659
|
+
end
|
660
|
+
```
|
661
|
+
|
662
|
+
## Build and Retrieve Scoped Records
|
663
|
+
|
664
|
+
Each of the seven core CRUD methods build and retrieve records using the `action_scope` method which by default returns the model class. In order to build or retrieve records using a scope it is possible to override this method.
|
665
|
+
|
666
|
+
```ruby
|
667
|
+
def action_scope
|
668
|
+
current_user.albums
|
669
|
+
end
|
670
|
+
```
|
671
|
+
|
611
672
|
## Attribute Value Parsing
|
612
673
|
|
613
674
|
### Date and DateTime Attribute Values
|
@@ -693,7 +754,7 @@ ActiveManageable includes the following attributes:
|
|
693
754
|
|
694
755
|
## Adding Bespoke Methods
|
695
756
|
|
696
|
-
The manager classes provide standard implementations of the seven core CRUD methods. These can be overwritten to perform custom business logic and the classes can also be extended to include the business logic for additional actions, both making use of the internal ActiveManageable methods and variables.
|
757
|
+
The manager classes provide standard implementations of the seven core CRUD methods. These can be extended or overwritten to perform custom business logic and the classes can also be extended to include the business logic for additional actions, both making use of the internal ActiveManageable methods and variables.
|
697
758
|
|
698
759
|
```ruby
|
699
760
|
def complete(id:)
|
@@ -733,11 +794,20 @@ After making changes:
|
|
733
794
|
|
734
795
|
1. run `rake spec` to run the tests and check the test coverage
|
735
796
|
2. run `open coverage/index.html` to view the test coverage report
|
736
|
-
3. run `bundle exec appraisal install` to install the appraisal dependencies
|
797
|
+
3. run `bundle exec appraisal install` to install the appraisal dependencies or `bundle exec appraisal update` to upgrade the appraisal dependencies
|
737
798
|
4. run `bundle exec appraisal rspec` to run the tests against different versions of activerecord & activesupport
|
738
799
|
5. run `bundle exec rubocop` to check the style of files
|
739
800
|
|
740
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
801
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
802
|
+
|
803
|
+
To release a new version:
|
804
|
+
|
805
|
+
1. update the version number in `version.rb`
|
806
|
+
2. update the change log in `CHANGELOG.md`
|
807
|
+
3. run `bundle` to update the `Gemfile.lock` version
|
808
|
+
4. commit the changes
|
809
|
+
5. run `bundle exec rake release` to create & push a git tag for the version and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
810
|
+
6. create a new release for the version on GitHub
|
741
811
|
|
742
812
|
## Contributing
|
743
813
|
|
@@ -7,21 +7,19 @@ module ActiveManageable
|
|
7
7
|
module CanCanCan
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
|
-
|
11
|
-
private
|
10
|
+
private
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def authorize(record:, action: nil)
|
13
|
+
action ||= @current_method
|
14
|
+
current_ability.authorize!(action, record)
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def authorization_scope
|
18
|
+
model_class.accessible_by(current_ability)
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
def current_ability
|
22
|
+
::Ability.new(current_user)
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -7,21 +7,19 @@ module ActiveManageable
|
|
7
7
|
module Pundit
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
|
-
|
11
|
-
private
|
10
|
+
private
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def authorize(record:, action: nil)
|
13
|
+
action ||= authorize_action
|
14
|
+
::Pundit.authorize(current_user, record, action)
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def authorization_scope
|
18
|
+
::Pundit.policy_scope(current_user, model_class)
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
def authorize_action
|
22
|
+
"#{@current_method}?".to_sym
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -4,12 +4,13 @@ module ActiveManageable
|
|
4
4
|
class_attribute :defaults, instance_writer: false, instance_predicate: false
|
5
5
|
class_attribute :module_initialize_state_methods, instance_writer: false, instance_predicate: false
|
6
6
|
|
7
|
-
|
7
|
+
attr_accessor :target
|
8
|
+
attr_reader :current_method, :attributes, :options
|
8
9
|
|
9
10
|
# target provides a common variable to use within the CRUD, auxiliary & library methods
|
10
11
|
# whereas the object & collection methods provide less ambiguous external access
|
11
|
-
|
12
|
-
|
12
|
+
alias_attribute :object, :target
|
13
|
+
alias_attribute :collection, :target
|
13
14
|
|
14
15
|
class << self
|
15
16
|
# Ruby method called when a child class inherits from a parent class
|
@@ -58,6 +59,8 @@ module ActiveManageable
|
|
58
59
|
include ActiveManageable::Authorization::Pundit
|
59
60
|
when :cancancan
|
60
61
|
include ActiveManageable::Authorization::CanCanCan
|
62
|
+
when Module
|
63
|
+
include ActiveManageable.configuration.authorization_library
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
@@ -65,6 +68,8 @@ module ActiveManageable
|
|
65
68
|
case ActiveManageable.configuration.search_library
|
66
69
|
when :ransack
|
67
70
|
include ActiveManageable::Search::Ransack
|
71
|
+
when Module
|
72
|
+
include ActiveManageable.configuration.search_library
|
68
73
|
end
|
69
74
|
end
|
70
75
|
|
@@ -72,6 +77,8 @@ module ActiveManageable
|
|
72
77
|
case ActiveManageable.configuration.pagination_library
|
73
78
|
when :kaminari
|
74
79
|
include ActiveManageable::Pagination::Kaminari
|
80
|
+
when Module
|
81
|
+
include ActiveManageable.configuration.pagination_library
|
75
82
|
end
|
76
83
|
end
|
77
84
|
|
@@ -109,6 +116,10 @@ module ActiveManageable
|
|
109
116
|
|
110
117
|
private
|
111
118
|
|
119
|
+
def action_scope
|
120
|
+
model_class
|
121
|
+
end
|
122
|
+
|
112
123
|
def initialize_state(attributes: {}, options: {})
|
113
124
|
@target = nil
|
114
125
|
@current_method = calling_method
|
@@ -6,31 +6,32 @@ module ActiveManageable
|
|
6
6
|
|
7
7
|
class Configuration
|
8
8
|
attr_reader :authorization_library, :search_library, :pagination_library, :default_loading_method
|
9
|
-
attr_accessor :subclass_suffix
|
9
|
+
attr_accessor :subclass_suffix, :paginate_without_count
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@default_loading_method = :includes
|
13
13
|
@subclass_suffix = "Manager"
|
14
|
+
@paginate_without_count = false
|
14
15
|
end
|
15
16
|
|
16
17
|
def authorization_library=(authorization_library)
|
17
18
|
raise ArgumentError.new("Invalid authorization library") unless authorization_library_valid?(authorization_library)
|
18
|
-
@authorization_library = authorization_library
|
19
|
+
@authorization_library = authorization_library
|
19
20
|
end
|
20
21
|
|
21
22
|
def search_library=(search_library)
|
22
23
|
raise ArgumentError.new("Invalid search library") unless search_library_valid?(search_library)
|
23
|
-
@search_library = search_library
|
24
|
+
@search_library = search_library
|
24
25
|
end
|
25
26
|
|
26
27
|
def pagination_library=(pagination_library)
|
27
28
|
raise ArgumentError.new("Invalid pagination library") unless pagination_library_valid?(pagination_library)
|
28
|
-
@pagination_library = pagination_library
|
29
|
+
@pagination_library = pagination_library
|
29
30
|
end
|
30
31
|
|
31
32
|
def default_loading_method=(default_loading_method)
|
32
33
|
raise ArgumentError.new("Invalid method for eager loading") unless default_loading_method_valid?(default_loading_method)
|
33
|
-
@default_loading_method = default_loading_method
|
34
|
+
@default_loading_method = default_loading_method
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
@@ -48,11 +49,19 @@ module ActiveManageable
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def default_loading_method_valid?(default_loading_method)
|
51
|
-
|
52
|
+
symbol_option_valid?(LOADING_METHODS, default_loading_method)
|
52
53
|
end
|
53
54
|
|
54
55
|
def option_valid?(options, option)
|
55
|
-
|
56
|
+
symbol_option_valid?(options, option) || module_option_valid?(option)
|
57
|
+
end
|
58
|
+
|
59
|
+
def symbol_option_valid?(options, option)
|
60
|
+
option.is_a?(Symbol) && options.include?(option.to_s.to_sym)
|
61
|
+
end
|
62
|
+
|
63
|
+
def module_option_valid?(option)
|
64
|
+
option.is_a?(Module)
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|