affairs_of_state 0.7.0 → 0.7.1
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 +17 -1
- data/lib/affairs_of_state/active_record_extension.rb +12 -10
- data/lib/affairs_of_state/config.rb +10 -2
- data/lib/affairs_of_state/version.rb +1 -1
- data/spec/affairs_of_state_spec.rb +45 -2
- data/spec/config_spec.rb +19 -1
- data/spec/spec_helper.rb +1 -0
- 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: 393e826c50c889d987390c00c48332b5f25b36dacc8977a4b6ae872b031507c0
|
|
4
|
+
data.tar.gz: 268729f4f4e5d03616028ae9ad663e9333ec77be659c1eb17ff4ba78f9ea44f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b28c839c99db9cf1a7560766f46bda687825c23e6d17c2f20b1246d239990f26a450e5a9350c10f1ea191678b929ecf88c0a389be7620d13f37e26d3d02525eb
|
|
7
|
+
data.tar.gz: 88a2b5f1cefe5ac0017eeaa9b2c2d480895b51f31497adf049a8ce54dbd3966f3c9e8f472d1b300e9d650c644ca1cb3b67063ddcbf7067e914e21c42d96a05f6
|
data/README.md
CHANGED
|
@@ -38,6 +38,12 @@ If you'd like to use another column, lets say `state`, pass it in as a configura
|
|
|
38
38
|
affairs_of_state :active, :inactive, column: :state
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
You can scope the helper and scope methods by a prefix:
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
affairs_of_state :active, :inactive, prefix: :admin
|
|
45
|
+
```
|
|
46
|
+
|
|
41
47
|
You can also turn off validation:
|
|
42
48
|
|
|
43
49
|
```ruby
|
|
@@ -72,6 +78,12 @@ widget = Widget.first
|
|
|
72
78
|
widget.cancelled! if widget.active?
|
|
73
79
|
```
|
|
74
80
|
|
|
81
|
+
These methods are scoped by the prefix if one is set:
|
|
82
|
+
```ruby
|
|
83
|
+
widget = Widget.first
|
|
84
|
+
widget.admin_cancelled! if widget.admin_active?
|
|
85
|
+
```
|
|
86
|
+
|
|
75
87
|
You can also access all your statuses on the model. If only one is defined it is default, otherwise the column name needs to be passed in:
|
|
76
88
|
|
|
77
89
|
```ruby
|
|
@@ -79,12 +91,16 @@ Widget.statuses # -> ["active", "cancelled"]
|
|
|
79
91
|
Widget.statuses(:status) # -> ["active", "cancelled"]
|
|
80
92
|
```
|
|
81
93
|
|
|
82
|
-
It also provides scopes automagically:
|
|
94
|
+
It also provides scopes automagically, scoped by prefix if one is set:
|
|
83
95
|
|
|
84
96
|
```ruby
|
|
85
97
|
Widget.active
|
|
86
98
|
Widget.cancelled
|
|
87
99
|
```
|
|
100
|
+
```ruby
|
|
101
|
+
Widget.admin_active
|
|
102
|
+
Widget.admin_cancelled
|
|
103
|
+
```
|
|
88
104
|
|
|
89
105
|
For select inputs in forms there is a convenience method that returns all states in the format expected by `options_for_select`. Again if only one is defined on the model it returns as default, if multiple are defined the column name needs to be passed in:
|
|
90
106
|
|
|
@@ -4,10 +4,11 @@ module AffairsOfState
|
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
|
|
6
6
|
class_methods do
|
|
7
|
-
def affairs_of_state(*statuses, column: :status, allow_blank: false, scopes: true, if: nil)
|
|
7
|
+
def affairs_of_state(*statuses, column: :status, allow_blank: false, scopes: true, if: nil, prefix: nil)
|
|
8
8
|
# config object that defines behaviour
|
|
9
9
|
config = AffairsOfState::Config.new(
|
|
10
10
|
statuses: statuses,
|
|
11
|
+
prefix: prefix,
|
|
11
12
|
column: column,
|
|
12
13
|
allow_blank: !!allow_blank,
|
|
13
14
|
scopes: scopes,
|
|
@@ -16,31 +17,32 @@ module AffairsOfState
|
|
|
16
17
|
|
|
17
18
|
# check for conflicts with existing calls
|
|
18
19
|
raise ArgumentError, "Affairs of State: #{ self } has already been called on `#{ config.column }`" if affairs_of_state_configs[config.column]
|
|
19
|
-
|
|
20
|
+
statuses_and_methods = affairs_of_state_configs.values.map(&:methods_for_statuses).map { |m| m.map{ |(k, v)| [k, v] } }.flatten
|
|
21
|
+
overlapping_statuses = statuses_and_methods & config.methods_for_statuses.map{ |k, v| [k, v] }.flatten
|
|
20
22
|
raise ArgumentError, "Affairs of State: #{ self } already has a status #{ overlapping_statuses }" if overlapping_statuses.any?
|
|
21
23
|
|
|
22
24
|
# status methods
|
|
23
|
-
config.
|
|
24
|
-
define_method("#{
|
|
25
|
+
config.methods_for_statuses.each do |status, method_name|
|
|
26
|
+
define_method("#{ method_name }?") do
|
|
25
27
|
self.send(config.column) == status
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
define_method("#{
|
|
30
|
+
define_method("#{ method_name }!") do
|
|
29
31
|
self.send("#{ config.column }=", status)
|
|
30
32
|
self.save
|
|
31
33
|
end
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
# column validation
|
|
35
|
-
validates(config.column, inclusion: { in: config.statuses, allow_blank: config.allow_blank }, if: config.if)
|
|
36
|
-
|
|
37
36
|
# scopes
|
|
38
37
|
if config.scopes
|
|
39
|
-
config.
|
|
40
|
-
self.scope(
|
|
38
|
+
config.methods_for_statuses.each do |status, method_name|
|
|
39
|
+
self.scope(method_name.to_sym, -> { where(config.column => status) })
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
|
|
43
|
+
# column validation
|
|
44
|
+
validates(config.column, inclusion: { in: config.statuses, allow_blank: config.allow_blank }, if: config.if)
|
|
45
|
+
|
|
44
46
|
# cache the config on the object
|
|
45
47
|
affairs_of_state_configs[config.column] = config
|
|
46
48
|
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module AffairsOfState
|
|
3
3
|
class Config
|
|
4
|
-
attr_reader :statuses, :column, :allow_blank, :scopes, :if
|
|
4
|
+
attr_reader :statuses, :column, :allow_blank, :scopes, :if, :methods_for_statuses
|
|
5
5
|
|
|
6
6
|
DISALLOWED_STATUSES = [ "new" ].freeze
|
|
7
7
|
|
|
8
|
-
def initialize(statuses:, column:, allow_blank:, scopes:, if:)
|
|
8
|
+
def initialize(statuses:, column:, allow_blank:, scopes:, if:, prefix:)
|
|
9
9
|
@column = column
|
|
10
10
|
@allow_blank = !!allow_blank
|
|
11
11
|
@scopes = !!scopes
|
|
12
12
|
@if = binding.local_variable_get(:if)
|
|
13
|
+
@prefix = prefix.presence
|
|
13
14
|
@statuses = statuses.flatten.map(&:to_s)
|
|
15
|
+
@methods_for_statuses = @statuses.to_h do |s|
|
|
16
|
+
if @prefix
|
|
17
|
+
[s.to_s, "#{ prefix }_#{ s }"]
|
|
18
|
+
else
|
|
19
|
+
[s.to_s, s.to_s]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
14
22
|
@statuses.each do |status|
|
|
15
23
|
raise ArgumentError.new("Affairs of State: '#{ status }' is not a valid status") if DISALLOWED_STATUSES.include?(status)
|
|
16
24
|
end
|
|
@@ -215,7 +215,7 @@ describe AffairsOfState do
|
|
|
215
215
|
|
|
216
216
|
it "raises if called twice on the same column" do
|
|
217
217
|
expect {
|
|
218
|
-
class
|
|
218
|
+
class Pie10 < ActiveRecord::Base
|
|
219
219
|
self.table_name = "pies"
|
|
220
220
|
|
|
221
221
|
affairs_of_state :active, :inactive
|
|
@@ -226,7 +226,7 @@ describe AffairsOfState do
|
|
|
226
226
|
|
|
227
227
|
it "raises if called twice with the same status in both" do
|
|
228
228
|
expect {
|
|
229
|
-
class
|
|
229
|
+
class Pie11 < ActiveRecord::Base
|
|
230
230
|
self.table_name = "pies"
|
|
231
231
|
|
|
232
232
|
affairs_of_state :active, :inactive
|
|
@@ -235,6 +235,17 @@ describe AffairsOfState do
|
|
|
235
235
|
}.to raise_error(ArgumentError)
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
+
it "raises if collision between prefixes" do
|
|
239
|
+
expect {
|
|
240
|
+
class Pie12 < ActiveRecord::Base
|
|
241
|
+
self.table_name = "pies"
|
|
242
|
+
|
|
243
|
+
affairs_of_state :admin_active, :admin_inactive
|
|
244
|
+
affairs_of_state :dormant, :active, column: :super_status, prefix: :admin
|
|
245
|
+
end
|
|
246
|
+
}.to raise_error(ArgumentError)
|
|
247
|
+
end
|
|
248
|
+
|
|
238
249
|
it "raises if statuses is called with no argument" do
|
|
239
250
|
expect {
|
|
240
251
|
subject.statuses
|
|
@@ -257,4 +268,36 @@ describe AffairsOfState do
|
|
|
257
268
|
expect(subject.statuses_for_select("super_status")).to eq([["Moderated", "moderated"], ["Unmoderated", "unmoderated"]])
|
|
258
269
|
end
|
|
259
270
|
end
|
|
271
|
+
|
|
272
|
+
describe "multiple invocations with prefix" do
|
|
273
|
+
class Pie13 < ActiveRecord::Base
|
|
274
|
+
self.table_name = "pies"
|
|
275
|
+
|
|
276
|
+
affairs_of_state :active, :inactive
|
|
277
|
+
affairs_of_state :moderated, :unmoderated, column: :super_status
|
|
278
|
+
affairs_of_state :positive, :mixed, :negative, column: :sentiment, prefix: :sentiment
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
subject { Pie13 }
|
|
282
|
+
|
|
283
|
+
it "returns the statuses" do
|
|
284
|
+
expect(subject.statuses(:sentiment)).to eq([ "positive", "mixed", "negative" ])
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "adds the setter and getter methods with the prefix" do
|
|
288
|
+
p = subject.new
|
|
289
|
+
expect(p).to_not be_sentiment_positive
|
|
290
|
+
expect(p).to_not be_sentiment_mixed
|
|
291
|
+
expect(p).to_not be_sentiment_negative
|
|
292
|
+
p.sentiment_mixed!
|
|
293
|
+
expect(p).to be_sentiment_mixed
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "adds the scopes with the prefix" do
|
|
297
|
+
p = subject.create! sentiment: "positive", status: "active", super_status: "unmoderated"
|
|
298
|
+
subject.create! sentiment: "mixed", status: "active", super_status: "unmoderated"
|
|
299
|
+
subject.create! sentiment: "negative", status: "active", super_status: "unmoderated"
|
|
300
|
+
expect(subject.sentiment_positive).to eq([p])
|
|
301
|
+
end
|
|
302
|
+
end
|
|
260
303
|
end
|
data/spec/config_spec.rb
CHANGED
|
@@ -8,7 +8,8 @@ describe AffairsOfState::Config do
|
|
|
8
8
|
column: column,
|
|
9
9
|
allow_blank: allow_blank,
|
|
10
10
|
scopes: scopes,
|
|
11
|
-
if: if_condition
|
|
11
|
+
if: if_condition,
|
|
12
|
+
prefix: prefix
|
|
12
13
|
)
|
|
13
14
|
end
|
|
14
15
|
let(:column) { "state" }
|
|
@@ -16,6 +17,7 @@ describe AffairsOfState::Config do
|
|
|
16
17
|
let(:allow_blank) { "sure" }
|
|
17
18
|
let(:scopes) { nil }
|
|
18
19
|
let(:if_condition) { "false" }
|
|
20
|
+
let(:prefix) { nil }
|
|
19
21
|
|
|
20
22
|
subject { config }
|
|
21
23
|
|
|
@@ -39,6 +41,10 @@ describe AffairsOfState::Config do
|
|
|
39
41
|
it "has :statuses and converts to strings and flattens" do
|
|
40
42
|
expect(subject.statuses).to eq(["created", "destroyed"])
|
|
41
43
|
end
|
|
44
|
+
|
|
45
|
+
it "has :methods_for_statuses which is the same key values" do
|
|
46
|
+
expect(subject.methods_for_statuses).to eq({ "created" => "created", "destroyed" => "destroyed" })
|
|
47
|
+
end
|
|
42
48
|
end
|
|
43
49
|
|
|
44
50
|
context "with invalid status" do
|
|
@@ -48,4 +54,16 @@ describe AffairsOfState::Config do
|
|
|
48
54
|
expect { subject }.to raise_error(ArgumentError, "Affairs of State: 'new' is not a valid status")
|
|
49
55
|
end
|
|
50
56
|
end
|
|
57
|
+
|
|
58
|
+
context "with prefix" do
|
|
59
|
+
let(:prefix) { :admin }
|
|
60
|
+
|
|
61
|
+
it "has :statuses just the same" do
|
|
62
|
+
expect(subject.statuses).to eq(["created", "destroyed"])
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "has :methods_for_statuses" do
|
|
66
|
+
expect(subject.methods_for_statuses).to eq({ "created" => "admin_created", "destroyed" => "admin_destroyed" })
|
|
67
|
+
end
|
|
68
|
+
end
|
|
51
69
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: affairs_of_state
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kevin McPhillips
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-12-
|
|
11
|
+
date: 2021-12-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|