affairs_of_state 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|