affairs_of_state 0.6.0 → 0.7.2
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/.github/workflows/ci.yml +1 -0
- data/.ruby_version +1 -0
- data/README.md +23 -5
- data/affairs_of_state.gemspec +3 -5
- data/gemfiles/activerecord-7.0.gemfile +5 -0
- data/lib/affairs_of_state/active_record_extension.rb +79 -0
- data/lib/affairs_of_state/config.rb +18 -7
- data/lib/affairs_of_state/version.rb +2 -1
- data/lib/affairs_of_state.rb +3 -56
- data/spec/affairs_of_state_spec.rb +150 -36
- data/spec/config_spec.rb +44 -22
- data/spec/spec_helper.rb +5 -2
- metadata +11 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 37d765f3c10fc68d7888ecde5f4b71736e70a85ccb77311f110f22772a5bfad3
|
|
4
|
+
data.tar.gz: 0b7a6965aad1f602356640b5d2c666bfcc60566e90fc54fd9c11cbd2394d92ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41dc25892417048d6de1ba7e6927ea335e7ce46819e834943358f5bf03b1397dad3e6aa846ea725a5eec162f5c7bc63e2b6ef8c1812e751683eeec255f868031
|
|
7
|
+
data.tar.gz: f28c08bebd42bf3c3a8b0a49308cc6f01161d5ad6840774ad4fb00f391e5d02e2d4730f6090acea7d274ade88b3eaf5e60eb651218da0563f1e4d21ac688a4f3
|
data/.github/workflows/ci.yml
CHANGED
data/.ruby_version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.2
|
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
|
|
@@ -60,7 +66,7 @@ or
|
|
|
60
66
|
affairs_of_state :active, :inactive, if: :only_validate_if_this_method_returns_true
|
|
61
67
|
```
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
It can be called multiple times per model, provided as each time is with a different column, and that none of the statuses overlap. If either of these are not true it will raise on load.
|
|
64
70
|
|
|
65
71
|
|
|
66
72
|
## Methods
|
|
@@ -72,23 +78,35 @@ widget = Widget.first
|
|
|
72
78
|
widget.cancelled! if widget.active?
|
|
73
79
|
```
|
|
74
80
|
|
|
75
|
-
|
|
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
|
+
|
|
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
|
|
78
|
-
Widget
|
|
90
|
+
Widget.statuses # -> ["active", "cancelled"]
|
|
91
|
+
Widget.statuses(:status) # -> ["active", "cancelled"]
|
|
79
92
|
```
|
|
80
93
|
|
|
81
|
-
It also provides scopes automagically:
|
|
94
|
+
It also provides scopes automagically, scoped by prefix if one is set:
|
|
82
95
|
|
|
83
96
|
```ruby
|
|
84
97
|
Widget.active
|
|
85
98
|
Widget.cancelled
|
|
86
99
|
```
|
|
100
|
+
```ruby
|
|
101
|
+
Widget.admin_active
|
|
102
|
+
Widget.admin_cancelled
|
|
103
|
+
```
|
|
87
104
|
|
|
88
|
-
For select inputs in forms there is a convenience method that returns all states in the format expected by `options_for_select
|
|
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:
|
|
89
106
|
|
|
90
107
|
```ruby
|
|
91
108
|
<%= f.select :status, options_for_select(Widget.statuses_for_select) %>
|
|
109
|
+
<%= f.select :status, options_for_select(Widget.statuses_for_select(:status)) %>
|
|
92
110
|
```
|
|
93
111
|
|
|
94
112
|
|
data/affairs_of_state.gemspec
CHANGED
|
@@ -19,9 +19,7 @@ Gem::Specification.new do |gem|
|
|
|
19
19
|
gem.add_dependency "activerecord", ">= 6.0"
|
|
20
20
|
gem.add_dependency "activesupport", ">= 6.0"
|
|
21
21
|
|
|
22
|
-
gem.add_development_dependency "rspec"
|
|
23
|
-
gem.add_development_dependency "sqlite3", "
|
|
24
|
-
gem.add_development_dependency "
|
|
25
|
-
gem.add_development_dependency "rake"
|
|
26
|
-
|
|
22
|
+
gem.add_development_dependency "rspec", ">= 3.0"
|
|
23
|
+
gem.add_development_dependency "sqlite3", ">= 1.4.0"
|
|
24
|
+
gem.add_development_dependency "rake", ">= 12"
|
|
27
25
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module AffairsOfState
|
|
3
|
+
module ActiveRecordExtension
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
class_methods do
|
|
7
|
+
def affairs_of_state(*statuses, column: :status, allow_blank: false, scopes: true, if: nil, prefix: nil)
|
|
8
|
+
# config object that defines behaviour
|
|
9
|
+
config = AffairsOfState::Config.new(
|
|
10
|
+
statuses: statuses,
|
|
11
|
+
prefix: prefix,
|
|
12
|
+
column: column,
|
|
13
|
+
allow_blank: !!allow_blank,
|
|
14
|
+
scopes: scopes,
|
|
15
|
+
if: binding.local_variable_get(:if)
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# check for conflicts with existing calls
|
|
19
|
+
raise ArgumentError, "Affairs of State: #{ self } has already been called on `#{ config.column }`" if affairs_of_state_configs[config.column]
|
|
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
|
|
22
|
+
raise ArgumentError, "Affairs of State: #{ self } already has a status #{ overlapping_statuses }" if overlapping_statuses.any?
|
|
23
|
+
|
|
24
|
+
# status methods
|
|
25
|
+
config.methods_for_statuses.each do |status, method_name|
|
|
26
|
+
define_method("#{ method_name }?") do
|
|
27
|
+
self.send(config.column) == status
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
define_method("#{ method_name }!") do
|
|
31
|
+
self.send("#{ config.column }=", status)
|
|
32
|
+
self.save
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# scopes
|
|
37
|
+
if config.scopes
|
|
38
|
+
config.methods_for_statuses.each do |status, method_name|
|
|
39
|
+
self.scope(method_name.to_sym, -> { where(config.column => status) })
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# column validation
|
|
44
|
+
validates(config.column, inclusion: { in: config.statuses, allow_blank: config.allow_blank }, if: config.if)
|
|
45
|
+
|
|
46
|
+
# cache the config on the object
|
|
47
|
+
affairs_of_state_configs[config.column] = config
|
|
48
|
+
|
|
49
|
+
include InstanceMethods
|
|
50
|
+
extend SingletonMethods
|
|
51
|
+
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def affairs_of_state_configs
|
|
56
|
+
@affairs_of_state_configs ||= {}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module InstanceMethods
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
module SingletonMethods
|
|
64
|
+
def statuses_for_select(column=nil)
|
|
65
|
+
statuses(column).map{ |s| [s.humanize, s] }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def statuses(column=nil)
|
|
69
|
+
if !column && affairs_of_state_configs.length == 1
|
|
70
|
+
affairs_of_state_configs.values.first.statuses
|
|
71
|
+
elsif !column && affairs_of_state_configs.length > 1
|
|
72
|
+
raise ArgumentError, "column is required"
|
|
73
|
+
elsif column
|
|
74
|
+
affairs_of_state_configs[column.to_sym]&.statuses
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module AffairsOfState
|
|
2
3
|
class Config
|
|
3
|
-
|
|
4
|
-
attr_reader :statuses
|
|
4
|
+
attr_reader :statuses, :column, :allow_blank, :scopes, :if, :methods_for_statuses
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
@statuses = val.flatten.map(&:to_s)
|
|
6
|
+
DISALLOWED_STATUSES = [ "new" ].freeze
|
|
8
7
|
|
|
8
|
+
def initialize(statuses:, column:, allow_blank:, scopes:, if:, prefix:)
|
|
9
|
+
@column = column
|
|
10
|
+
@allow_blank = !!allow_blank
|
|
11
|
+
@scopes = !!scopes
|
|
12
|
+
@if = binding.local_variable_get(:if)
|
|
13
|
+
@prefix = prefix.presence
|
|
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
|
|
9
22
|
@statuses.each do |status|
|
|
10
|
-
raise ArgumentError.new("Affairs of State: '#{ status }' is not a valid status") if
|
|
23
|
+
raise ArgumentError.new("Affairs of State: '#{ status }' is not a valid status") if DISALLOWED_STATUSES.include?(status)
|
|
11
24
|
end
|
|
12
|
-
|
|
13
|
-
@statuses
|
|
14
25
|
end
|
|
15
26
|
end
|
|
16
27
|
end
|
data/lib/affairs_of_state.rb
CHANGED
|
@@ -1,65 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "active_support"
|
|
2
3
|
require "active_support/concern"
|
|
3
4
|
require "active_record"
|
|
4
5
|
|
|
5
6
|
require "affairs_of_state/version"
|
|
6
7
|
require "affairs_of_state/config"
|
|
7
|
-
|
|
8
|
-
module AffairsOfState
|
|
9
|
-
extend ActiveSupport::Concern
|
|
10
|
-
|
|
11
|
-
class_methods do
|
|
12
|
-
def affairs_of_state(*statuses, column: :status, allow_blank: false, scopes: true, if: nil)
|
|
13
|
-
raise ArgumentError.new("Affairs of State: cannot be invoked multiple times on the same model") if @affairs_of_state_config
|
|
14
|
-
|
|
15
|
-
affairs_of_state_config.statuses = statuses
|
|
16
|
-
affairs_of_state_config.column = column
|
|
17
|
-
affairs_of_state_config.allow_blank = allow_blank
|
|
18
|
-
affairs_of_state_config.scopes = scopes
|
|
19
|
-
affairs_of_state_config.if = binding.local_variable_get(:if)
|
|
20
|
-
|
|
21
|
-
const_set(:STATUSES, affairs_of_state_config.statuses)
|
|
22
|
-
|
|
23
|
-
affairs_of_state_config.statuses.each do |status|
|
|
24
|
-
define_method("#{ status }?") do
|
|
25
|
-
self.send(self.class.affairs_of_state_config.column) == status
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
define_method("#{ status }!") do
|
|
29
|
-
self.send("#{ self.class.affairs_of_state_config.column }=", status)
|
|
30
|
-
self.save
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
validates(affairs_of_state_config.column, inclusion: { in: affairs_of_state_config.statuses, allow_blank: affairs_of_state_config.allow_blank }, if: affairs_of_state_config.if)
|
|
35
|
-
|
|
36
|
-
if affairs_of_state_config.scopes
|
|
37
|
-
affairs_of_state_config.statuses.each do |status|
|
|
38
|
-
self.scope(status.to_sym, -> { where(affairs_of_state_config.column => status) })
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
include InstanceMethods
|
|
43
|
-
extend SingletonMethods
|
|
44
|
-
|
|
45
|
-
true
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def affairs_of_state_config
|
|
49
|
-
@affairs_of_state_config ||= AffairsOfState::Config.new
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
module InstanceMethods
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
module SingletonMethods
|
|
57
|
-
def statuses_for_select
|
|
58
|
-
affairs_of_state_config.statuses.map{ |s| [s.humanize, s] }
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
8
|
+
require "affairs_of_state/active_record_extension"
|
|
62
9
|
|
|
63
10
|
ActiveSupport.on_load(:active_record) do
|
|
64
|
-
::ActiveRecord::Base.send :include, AffairsOfState
|
|
11
|
+
::ActiveRecord::Base.send :include, AffairsOfState::ActiveRecordExtension
|
|
65
12
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'spec_helper'
|
|
2
3
|
|
|
3
4
|
describe AffairsOfState do
|
|
@@ -6,57 +7,63 @@ describe AffairsOfState do
|
|
|
6
7
|
affairs_of_state :active, :inactive, :cancelled
|
|
7
8
|
end
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
expect(Pie::STATUSES).to eq(["active", "inactive", "cancelled"])
|
|
11
|
-
end
|
|
10
|
+
subject { Pie }
|
|
12
11
|
|
|
13
12
|
it "should validate the column is set" do
|
|
14
|
-
expect(
|
|
13
|
+
expect(subject.new(status: nil)).to_not be_valid
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
it "should validate that we're not setting it to something stupid" do
|
|
18
|
-
expect(
|
|
17
|
+
expect(subject.new(status: "delicious_pie")).to_not be_valid
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
describe "boolean methods" do
|
|
22
21
|
it "should find the set status" do
|
|
23
|
-
p =
|
|
22
|
+
p = subject.new status: "active"
|
|
24
23
|
expect(p.active?).to be_truthy
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
it "should not find if a different status is set" do
|
|
28
|
-
p =
|
|
27
|
+
p = subject.new status: "inactive"
|
|
29
28
|
expect(p.cancelled?).to be_falsy
|
|
30
29
|
end
|
|
31
30
|
end
|
|
32
31
|
|
|
33
32
|
describe "update methods" do
|
|
34
33
|
it "should set the value" do
|
|
35
|
-
p =
|
|
34
|
+
p = subject.create! status: "active"
|
|
36
35
|
expect(p.inactive!).to be_truthy
|
|
37
36
|
expect(p.status).to eq("inactive")
|
|
38
37
|
end
|
|
39
38
|
end
|
|
40
39
|
|
|
40
|
+
it "should have the statuses method with the nil default" do
|
|
41
|
+
expect(subject.statuses).to eq(["active", "inactive", "cancelled"])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should have the statuses method" do
|
|
45
|
+
expect(subject.statuses(:status)).to eq(["active", "inactive", "cancelled"])
|
|
46
|
+
end
|
|
47
|
+
|
|
41
48
|
it "should provide a method to pass to dropdowns" do
|
|
42
|
-
expect(
|
|
49
|
+
expect(subject.statuses_for_select).to eq([["Active", "active"], ["Inactive", "inactive"], ["Cancelled", "cancelled"]])
|
|
43
50
|
end
|
|
44
51
|
|
|
45
52
|
describe "scopes" do
|
|
46
53
|
it "should have a finder to match the status name" do
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
expect(
|
|
53
|
-
expect(
|
|
54
|
-
expect(
|
|
54
|
+
subject.create! status: "active"
|
|
55
|
+
subject.create! status: "inactive"
|
|
56
|
+
subject.create! status: "active"
|
|
57
|
+
subject.create! status: "cancelled"
|
|
58
|
+
|
|
59
|
+
expect(subject.active.size).to eq(2)
|
|
60
|
+
expect(subject.inactive.size).to eq(1)
|
|
61
|
+
expect(subject.cancelled.size).to eq(1)
|
|
55
62
|
end
|
|
56
63
|
end
|
|
57
64
|
|
|
58
65
|
after(:each) do
|
|
59
|
-
|
|
66
|
+
subject.destroy_all
|
|
60
67
|
end
|
|
61
68
|
end
|
|
62
69
|
|
|
@@ -67,16 +74,18 @@ describe AffairsOfState do
|
|
|
67
74
|
affairs_of_state :active, :inactive, column: :super_status
|
|
68
75
|
end
|
|
69
76
|
|
|
77
|
+
subject { Pie2 }
|
|
78
|
+
|
|
70
79
|
it "should validate the column is set" do
|
|
71
|
-
expect(
|
|
80
|
+
expect(subject.new(status: nil, super_status: "active")).to be_valid
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
it "should know the accessors" do
|
|
75
|
-
expect(
|
|
84
|
+
expect(subject.new(status: nil, super_status: "inactive").inactive?).to be(true)
|
|
76
85
|
end
|
|
77
86
|
|
|
78
87
|
it "should know the setters" do
|
|
79
|
-
instance =
|
|
88
|
+
instance = subject.create!(status: nil, super_status: "inactive")
|
|
80
89
|
expect(instance.active!).to be(true)
|
|
81
90
|
expect(instance.super_status).to eq("active")
|
|
82
91
|
end
|
|
@@ -89,8 +98,10 @@ describe AffairsOfState do
|
|
|
89
98
|
affairs_of_state :active, :inactive, allow_blank: true
|
|
90
99
|
end
|
|
91
100
|
|
|
101
|
+
subject { Pie3 }
|
|
102
|
+
|
|
92
103
|
it "should validate the column is set" do
|
|
93
|
-
expect(
|
|
104
|
+
expect(subject.new(status: nil)).to be_valid
|
|
94
105
|
end
|
|
95
106
|
end
|
|
96
107
|
|
|
@@ -101,8 +112,10 @@ describe AffairsOfState do
|
|
|
101
112
|
affairs_of_state [:on, :off]
|
|
102
113
|
end
|
|
103
114
|
|
|
115
|
+
subject { Pie4 }
|
|
116
|
+
|
|
104
117
|
it "should work too if that's what floats your boat" do
|
|
105
|
-
expect(
|
|
118
|
+
expect(subject.statuses).to eq(["on", "off"])
|
|
106
119
|
end
|
|
107
120
|
end
|
|
108
121
|
|
|
@@ -113,8 +126,10 @@ describe AffairsOfState do
|
|
|
113
126
|
affairs_of_state :active, :inactive, scopes: false
|
|
114
127
|
end
|
|
115
128
|
|
|
116
|
-
|
|
117
|
-
|
|
129
|
+
subject { Pie5 }
|
|
130
|
+
|
|
131
|
+
it "should not respond if the scopes are not needed" do
|
|
132
|
+
expect(subject).to_not respond_to(:active)
|
|
118
133
|
end
|
|
119
134
|
end
|
|
120
135
|
|
|
@@ -127,15 +142,17 @@ describe AffairsOfState do
|
|
|
127
142
|
attr_accessor :is_going_to_validate
|
|
128
143
|
end
|
|
129
144
|
|
|
145
|
+
subject { Pie6 }
|
|
146
|
+
|
|
130
147
|
it "should enforce the validation if the :if param is true" do
|
|
131
|
-
p =
|
|
148
|
+
p = subject.new
|
|
132
149
|
p.is_going_to_validate = true
|
|
133
150
|
p.status = "pie"
|
|
134
151
|
expect(p).to_not be_valid
|
|
135
152
|
end
|
|
136
153
|
|
|
137
154
|
it "should not enforce the validation if the :if param evaluates to false" do
|
|
138
|
-
p =
|
|
155
|
+
p = subject.new
|
|
139
156
|
p.is_going_to_validate = false
|
|
140
157
|
p.status = "pie"
|
|
141
158
|
expect(p).to be_valid
|
|
@@ -155,15 +172,17 @@ describe AffairsOfState do
|
|
|
155
172
|
end
|
|
156
173
|
end
|
|
157
174
|
|
|
175
|
+
subject { Pie7 }
|
|
176
|
+
|
|
158
177
|
it "should enforce the validation if the :if param is true" do
|
|
159
|
-
p =
|
|
178
|
+
p = subject.new
|
|
160
179
|
p.is_going_to_validate = true
|
|
161
180
|
p.status = "pie"
|
|
162
181
|
expect(p).to_not be_valid
|
|
163
182
|
end
|
|
164
183
|
|
|
165
184
|
it "should not enforce the validation if the :if param evaluates to false" do
|
|
166
|
-
p =
|
|
185
|
+
p = subject.new
|
|
167
186
|
p.is_going_to_validate = false
|
|
168
187
|
p.status = "pie"
|
|
169
188
|
expect(p).to be_valid
|
|
@@ -172,18 +191,113 @@ describe AffairsOfState do
|
|
|
172
191
|
|
|
173
192
|
describe "invalid status name" do
|
|
174
193
|
it "should raise a good warning" do
|
|
175
|
-
expect
|
|
194
|
+
expect{ class Pie8 < ActiveRecord::Base ; affairs_of_state :new ; end }.to raise_error(ArgumentError, "Affairs of State: 'new' is not a valid status")
|
|
176
195
|
end
|
|
177
196
|
end
|
|
178
197
|
|
|
179
198
|
describe "multiple invocations" do
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
class Pie9 < ActiveRecord::Base
|
|
200
|
+
self.table_name = "pies"
|
|
201
|
+
|
|
202
|
+
affairs_of_state :active, :inactive
|
|
203
|
+
affairs_of_state :moderated, :unmoderated, column: :super_status
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
subject { Pie9 }
|
|
207
|
+
|
|
208
|
+
it "declares two status columns" do
|
|
209
|
+
p = subject.new
|
|
210
|
+
p.inactive!
|
|
211
|
+
p.unmoderated!
|
|
212
|
+
expect(p).to be_inactive
|
|
213
|
+
expect(p).to be_unmoderated
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "raises if called twice on the same column" do
|
|
217
|
+
expect {
|
|
218
|
+
class Pie10 < ActiveRecord::Base
|
|
219
|
+
self.table_name = "pies"
|
|
220
|
+
|
|
221
|
+
affairs_of_state :active, :inactive
|
|
222
|
+
affairs_of_state :moderated, :unmoderated
|
|
223
|
+
end
|
|
224
|
+
}.to raise_error(ArgumentError)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "raises if called twice with the same status in both" do
|
|
228
|
+
expect {
|
|
229
|
+
class Pie11 < ActiveRecord::Base
|
|
230
|
+
self.table_name = "pies"
|
|
231
|
+
|
|
232
|
+
affairs_of_state :active, :inactive
|
|
233
|
+
affairs_of_state :dormant, :active, column: :super_status
|
|
185
234
|
end
|
|
186
|
-
}
|
|
235
|
+
}.to raise_error(ArgumentError)
|
|
236
|
+
end
|
|
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
|
+
|
|
249
|
+
it "raises if statuses is called with no argument" do
|
|
250
|
+
expect {
|
|
251
|
+
subject.statuses
|
|
252
|
+
}.to raise_error(ArgumentError)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "returns the statuses for the column" do
|
|
256
|
+
expect(subject.statuses(:status)).to eq(["active", "inactive"])
|
|
257
|
+
expect(subject.statuses("super_status")).to eq(["moderated", "unmoderated"])
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "raises if statuses_for_select is called with no argument" do
|
|
261
|
+
expect {
|
|
262
|
+
subject.statuses_for_select
|
|
263
|
+
}.to raise_error(ArgumentError)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "returns the statuses_for_select for the column" do
|
|
267
|
+
expect(subject.statuses_for_select(:status)).to eq([["Active", "active"], ["Inactive", "inactive"]])
|
|
268
|
+
expect(subject.statuses_for_select("super_status")).to eq([["Moderated", "moderated"], ["Unmoderated", "unmoderated"]])
|
|
269
|
+
end
|
|
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])
|
|
187
301
|
end
|
|
188
302
|
end
|
|
189
303
|
end
|
data/spec/config_spec.rb
CHANGED
|
@@ -1,47 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'spec_helper'
|
|
2
3
|
|
|
3
4
|
describe AffairsOfState::Config do
|
|
4
|
-
|
|
5
|
+
let(:config) do
|
|
6
|
+
AffairsOfState::Config.new(
|
|
7
|
+
statuses: statuses,
|
|
8
|
+
column: column,
|
|
9
|
+
allow_blank: allow_blank,
|
|
10
|
+
scopes: scopes,
|
|
11
|
+
if: if_condition,
|
|
12
|
+
prefix: prefix
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
let(:column) { "state" }
|
|
16
|
+
let(:statuses) { [ :created, [ :destroyed ] ] }
|
|
17
|
+
let(:allow_blank) { "sure" }
|
|
18
|
+
let(:scopes) { nil }
|
|
19
|
+
let(:if_condition) { "false" }
|
|
20
|
+
let(:prefix) { nil }
|
|
5
21
|
|
|
6
|
-
|
|
7
|
-
let(:expected){ double }
|
|
22
|
+
subject { config }
|
|
8
23
|
|
|
24
|
+
describe "accessors" do
|
|
9
25
|
it "has :column" do
|
|
10
|
-
subject.column
|
|
11
|
-
expect(subject.column).to eq(expected)
|
|
26
|
+
expect(subject.column).to eq(column)
|
|
12
27
|
end
|
|
13
28
|
|
|
14
29
|
it "has :allow_blank" do
|
|
15
|
-
subject.allow_blank
|
|
16
|
-
expect(subject.allow_blank).to eq(expected)
|
|
30
|
+
expect(subject.allow_blank).to be(true)
|
|
17
31
|
end
|
|
18
32
|
|
|
19
33
|
it "has :scopes" do
|
|
20
|
-
subject.scopes
|
|
21
|
-
expect(subject.scopes).to eq(expected)
|
|
34
|
+
expect(subject.scopes).to be(false)
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
it "has :if" do
|
|
25
|
-
subject.if
|
|
26
|
-
expect(subject.if).to eq(expected)
|
|
38
|
+
expect(subject.if).to eq(if_condition)
|
|
27
39
|
end
|
|
28
|
-
end
|
|
29
40
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
subject.statuses = [:a, :b]
|
|
33
|
-
expect(subject.statuses).to eq(["a", "b"])
|
|
41
|
+
it "has :statuses and converts to strings and flattens" do
|
|
42
|
+
expect(subject.statuses).to eq(["created", "destroyed"])
|
|
34
43
|
end
|
|
35
44
|
|
|
36
|
-
it "
|
|
37
|
-
subject.
|
|
38
|
-
expect(subject.statuses).to eq(["a", "b"])
|
|
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" })
|
|
39
47
|
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "with invalid status" do
|
|
51
|
+
let(:statuses) { [ "new" ] }
|
|
40
52
|
|
|
41
53
|
it "makes sure no invalid statuses are allowed" do
|
|
42
|
-
expect(
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
expect { subject }.to raise_error(ArgumentError, "Affairs of State: 'new' is not a valid status")
|
|
55
|
+
end
|
|
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" })
|
|
45
67
|
end
|
|
46
68
|
end
|
|
47
69
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "affairs_of_state"
|
|
2
3
|
|
|
3
|
-
require "pry"
|
|
4
4
|
require "sqlite3"
|
|
5
5
|
|
|
6
6
|
RSpec.configure do |config|
|
|
7
7
|
config.run_all_when_everything_filtered = true
|
|
8
|
+
config.filter_run_when_matching :focus
|
|
9
|
+
# config.raise_errors_for_deprecations!
|
|
8
10
|
end
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
# Create an AR model to test with
|
|
11
13
|
I18n.enforce_available_locales = false
|
|
12
14
|
|
|
13
15
|
ActiveRecord::Base.establish_connection(
|
|
@@ -19,4 +21,5 @@ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'pies'")
|
|
|
19
21
|
ActiveRecord::Base.connection.create_table(:pies) do |t|
|
|
20
22
|
t.string :status
|
|
21
23
|
t.string :super_status
|
|
24
|
+
t.string :sentiment
|
|
22
25
|
end
|
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.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kevin McPhillips
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-09-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -44,56 +44,42 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0'
|
|
47
|
+
version: '3.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '0'
|
|
54
|
+
version: '3.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: sqlite3
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: 1.4.0
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: 1.4.0
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: pry
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
72
58
|
requirements:
|
|
73
59
|
- - ">="
|
|
74
60
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
61
|
+
version: 1.4.0
|
|
76
62
|
type: :development
|
|
77
63
|
prerelease: false
|
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
65
|
requirements:
|
|
80
66
|
- - ">="
|
|
81
67
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
68
|
+
version: 1.4.0
|
|
83
69
|
- !ruby/object:Gem::Dependency
|
|
84
70
|
name: rake
|
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
|
86
72
|
requirements:
|
|
87
73
|
- - ">="
|
|
88
74
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
75
|
+
version: '12'
|
|
90
76
|
type: :development
|
|
91
77
|
prerelease: false
|
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
79
|
requirements:
|
|
94
80
|
- - ">="
|
|
95
81
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
82
|
+
version: '12'
|
|
97
83
|
description: Add a simple state to a gem, without all the hassle of a complex state
|
|
98
84
|
machine.
|
|
99
85
|
email:
|
|
@@ -105,6 +91,7 @@ files:
|
|
|
105
91
|
- ".github/workflows/ci.yml"
|
|
106
92
|
- ".gitignore"
|
|
107
93
|
- ".rspec"
|
|
94
|
+
- ".ruby_version"
|
|
108
95
|
- Gemfile
|
|
109
96
|
- LICENSE
|
|
110
97
|
- README.md
|
|
@@ -112,8 +99,10 @@ files:
|
|
|
112
99
|
- affairs_of_state.gemspec
|
|
113
100
|
- gemfiles/activerecord-6.0.gemfile
|
|
114
101
|
- gemfiles/activerecord-6.1.gemfile
|
|
102
|
+
- gemfiles/activerecord-7.0.gemfile
|
|
115
103
|
- gemfiles/activerecord-latest.gemfile
|
|
116
104
|
- lib/affairs_of_state.rb
|
|
105
|
+
- lib/affairs_of_state/active_record_extension.rb
|
|
117
106
|
- lib/affairs_of_state/config.rb
|
|
118
107
|
- lib/affairs_of_state/version.rb
|
|
119
108
|
- spec/affairs_of_state_spec.rb
|