careacademy-enumerize 2.8.0
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 +7 -0
- data/.github/workflows/ruby.yml +69 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +327 -0
- data/Gemfile +6 -0
- data/Gemfile.global +12 -0
- data/Gemfile.mongo_mapper +6 -0
- data/Gemfile.rails60 +6 -0
- data/Gemfile.rails61 +6 -0
- data/Gemfile.rails70 +9 -0
- data/Gemfile.railsmaster +5 -0
- data/MIT-LICENSE +22 -0
- data/README.md +641 -0
- data/Rakefile +17 -0
- data/enumerize.gemspec +22 -0
- data/lib/enumerize/activemodel.rb +47 -0
- data/lib/enumerize/activerecord.rb +142 -0
- data/lib/enumerize/attribute.rb +192 -0
- data/lib/enumerize/attribute_map.rb +40 -0
- data/lib/enumerize/base.rb +112 -0
- data/lib/enumerize/hooks/formtastic.rb +27 -0
- data/lib/enumerize/hooks/sequel_dataset.rb +17 -0
- data/lib/enumerize/hooks/simple_form.rb +37 -0
- data/lib/enumerize/hooks/uniqueness.rb +22 -0
- data/lib/enumerize/integrations/rails_admin.rb +18 -0
- data/lib/enumerize/integrations/rspec/matcher.rb +164 -0
- data/lib/enumerize/integrations/rspec.rb +19 -0
- data/lib/enumerize/module.rb +33 -0
- data/lib/enumerize/module_attributes.rb +12 -0
- data/lib/enumerize/mongoid.rb +29 -0
- data/lib/enumerize/predicatable.rb +23 -0
- data/lib/enumerize/predicates.rb +76 -0
- data/lib/enumerize/scope/activerecord.rb +53 -0
- data/lib/enumerize/scope/mongoid.rb +50 -0
- data/lib/enumerize/scope/sequel.rb +56 -0
- data/lib/enumerize/sequel.rb +62 -0
- data/lib/enumerize/set.rb +81 -0
- data/lib/enumerize/utils.rb +12 -0
- data/lib/enumerize/value.rb +47 -0
- data/lib/enumerize/version.rb +5 -0
- data/lib/enumerize.rb +90 -0
- data/lib/sequel/plugins/enumerize.rb +18 -0
- data/spec/enumerize/integrations/rspec/matcher_spec.rb +261 -0
- data/spec/spec_helper.rb +30 -0
- data/test/activemodel_test.rb +114 -0
- data/test/activerecord_test.rb +679 -0
- data/test/attribute_map_test.rb +70 -0
- data/test/attribute_test.rb +141 -0
- data/test/base_test.rb +230 -0
- data/test/formtastic_test.rb +152 -0
- data/test/module_attributes_test.rb +52 -0
- data/test/mongo_mapper_test.rb +83 -0
- data/test/mongoid_test.rb +164 -0
- data/test/multiple_test.rb +65 -0
- data/test/predicates_test.rb +65 -0
- data/test/rails_admin_test.rb +27 -0
- data/test/sequel_test.rb +344 -0
- data/test/set_test.rb +166 -0
- data/test/simple_form_test.rb +156 -0
- data/test/support/mock_controller.rb +31 -0
- data/test/support/shared_enums.rb +43 -0
- data/test/support/view_test_helper.rb +46 -0
- data/test/test_helper.rb +53 -0
- data/test/value_test.rb +158 -0
- metadata +143 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Integrations
|
5
|
+
module RSpec
|
6
|
+
class Matcher
|
7
|
+
|
8
|
+
def initialize(expected_attr)
|
9
|
+
self.expected_attr = expected_attr
|
10
|
+
end
|
11
|
+
|
12
|
+
def in(*expected_values)
|
13
|
+
self.expected_values = expected_values.flatten
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_default(expected_default)
|
18
|
+
self.expected_default = expected_default.to_s
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_i18n_scope(expected_i18n_scope)
|
23
|
+
self.expected_i18n_scope = expected_i18n_scope
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_predicates(expected_predicates)
|
28
|
+
self.expected_predicates = expected_predicates
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def with_multiple(expected_multiple)
|
33
|
+
self.expected_multiple = expected_multiple
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def with_scope(expected_scope)
|
38
|
+
self.expected_scope = expected_scope
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure_message
|
43
|
+
"Expected #{expectation}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def failure_message_when_negated
|
47
|
+
"Did not expect #{expectation}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def description
|
51
|
+
description = "define enumerize :#{expected_attr}"
|
52
|
+
description += " in: #{quote_values(expected_values)}" if expected_values
|
53
|
+
description += " with #{expected_default.inspect} as default value" if expected_default
|
54
|
+
description += " i18n_scope: #{expected_i18n_scope.inspect}" if expected_i18n_scope
|
55
|
+
description += " predicates: #{expected_predicates.inspect}" if expected_predicates
|
56
|
+
description += " multiple: #{expected_multiple.inspect}" if expected_multiple
|
57
|
+
description += " scope: #{expected_scope.inspect}" if expected_scope
|
58
|
+
|
59
|
+
description
|
60
|
+
end
|
61
|
+
|
62
|
+
def matches?(subject)
|
63
|
+
self.subject = subject
|
64
|
+
matches = true
|
65
|
+
|
66
|
+
matches &= matches_attribute?
|
67
|
+
matches &= matches_values? if expected_values
|
68
|
+
matches &= matches_default_value? if expected_default
|
69
|
+
matches &= matches_i18n_scope? if expected_i18n_scope
|
70
|
+
matches &= matches_predicates? if expected_predicates
|
71
|
+
matches &= matches_multiple? if expected_multiple
|
72
|
+
matches &= matches_scope? if expected_scope
|
73
|
+
|
74
|
+
matches
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
attr_accessor :expected_attr, :expected_values, :subject, :expected_default,
|
79
|
+
:expected_i18n_scope, :expected_predicates, :expected_multiple,
|
80
|
+
:expected_scope
|
81
|
+
|
82
|
+
def expectation
|
83
|
+
"#{subject.class.name} to #{description}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def matches_attribute?
|
87
|
+
attributes.present?
|
88
|
+
end
|
89
|
+
|
90
|
+
def matches_values?
|
91
|
+
matches_array_values? || matches_hash_values?
|
92
|
+
end
|
93
|
+
|
94
|
+
def matches_array_values?
|
95
|
+
sorted_values == enumerized_values
|
96
|
+
end
|
97
|
+
|
98
|
+
def matches_hash_values?
|
99
|
+
return unless expected_values.first.is_a?(Hash)
|
100
|
+
expected_values.first.all? { |k, v| enumerized_value_hash[k.to_s] == v; }
|
101
|
+
end
|
102
|
+
|
103
|
+
def matches_default_value?
|
104
|
+
expected_default == enumerized_default
|
105
|
+
end
|
106
|
+
|
107
|
+
def matches_i18n_scope?
|
108
|
+
attributes.i18n_scope == expected_i18n_scope
|
109
|
+
end
|
110
|
+
|
111
|
+
def matches_predicates?
|
112
|
+
if expected_predicates.is_a?(TrueClass)
|
113
|
+
subject.respond_to?("#{enumerized_values.first}?")
|
114
|
+
else
|
115
|
+
subject.respond_to?("#{expected_attr}_#{attributes.values.first}?")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def matches_multiple?
|
120
|
+
subject.public_send(expected_attr).is_a?(Enumerize::Set)
|
121
|
+
end
|
122
|
+
|
123
|
+
def matches_scope?
|
124
|
+
case expected_scope
|
125
|
+
when TrueClass
|
126
|
+
subject_class.respond_to?("with_#{expected_attr}")
|
127
|
+
when :shallow
|
128
|
+
enumerized_values.all? { |value| subject_class.respond_to?(value) }
|
129
|
+
else
|
130
|
+
subject_class.respond_to?(expected_scope[:scope])
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def sorted_values
|
135
|
+
@sorted_values ||=expected_values.map(&:to_s).sort
|
136
|
+
end
|
137
|
+
|
138
|
+
def enumerized_values
|
139
|
+
@enumerized_values ||= attributes.values.sort
|
140
|
+
end
|
141
|
+
|
142
|
+
def enumerized_default
|
143
|
+
@enumerized_default ||= attributes.default_value
|
144
|
+
end
|
145
|
+
|
146
|
+
def enumerized_value_hash
|
147
|
+
@enumerized_value_hash ||= attributes.instance_variable_get('@value_hash')
|
148
|
+
end
|
149
|
+
|
150
|
+
def attributes
|
151
|
+
subject_class.enumerized_attributes.attributes[expected_attr.to_s]
|
152
|
+
end
|
153
|
+
|
154
|
+
def subject_class
|
155
|
+
@subject_class ||= subject.class
|
156
|
+
end
|
157
|
+
|
158
|
+
def quote_values(values)
|
159
|
+
sorted_values.map(&:inspect).join(', ')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'enumerize/integrations/rspec/matcher'
|
4
|
+
|
5
|
+
module Enumerize
|
6
|
+
module Integrations
|
7
|
+
module RSpec
|
8
|
+
def enumerize(attr)
|
9
|
+
::Enumerize::Integrations::RSpec::Matcher.new(attr)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module RSpec
|
16
|
+
module Matchers
|
17
|
+
include Enumerize::Integrations::RSpec
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
class Module < ::Module
|
5
|
+
attr_reader :_class_methods
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
|
10
|
+
@_class_methods = ::Module.new
|
11
|
+
@_dependents = []
|
12
|
+
@_dependent_evals = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def included(klass)
|
16
|
+
klass.extend _class_methods
|
17
|
+
|
18
|
+
@_dependent_evals.each do |block|
|
19
|
+
klass.instance_eval(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
@_dependents << klass
|
23
|
+
end
|
24
|
+
|
25
|
+
def dependent_eval(&block)
|
26
|
+
@_dependents.each do |klass|
|
27
|
+
klass.instance_eval(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
@_dependent_evals << block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module MongoidSupport
|
5
|
+
def enumerize(name, options={})
|
6
|
+
super
|
7
|
+
|
8
|
+
_enumerize_module.dependent_eval do
|
9
|
+
if self < ::Mongoid::Document
|
10
|
+
include InstanceMethods
|
11
|
+
|
12
|
+
after_initialize :_set_default_value_for_enumerized_attributes
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def reload
|
19
|
+
reloaded = super
|
20
|
+
|
21
|
+
reloaded.class.enumerized_attributes.each do |attr|
|
22
|
+
reloaded.send("#{attr.name}=", reloaded[attr.name])
|
23
|
+
end
|
24
|
+
|
25
|
+
reloaded
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Predicatable
|
5
|
+
def respond_to_missing?(method, include_private=false)
|
6
|
+
predicate_method?(method) || super
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def method_missing(method, *args, &block)
|
12
|
+
if predicate_method?(method)
|
13
|
+
predicate_call(method[0..-2], *args, &block)
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def predicate_method?(method)
|
20
|
+
method[-1] == '?' && @attr && @attr.values.include?(method[0..-2])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
|
5
|
+
module Enumerize
|
6
|
+
# Predicate methods.
|
7
|
+
#
|
8
|
+
# Basic usage:
|
9
|
+
#
|
10
|
+
# class User
|
11
|
+
# extend Enumerize
|
12
|
+
# enumerize :sex, in: %w(male female), predicates: true
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# user = User.new
|
16
|
+
#
|
17
|
+
# user.male? # => false
|
18
|
+
# user.female? # => false
|
19
|
+
#
|
20
|
+
# user.sex = 'male'
|
21
|
+
#
|
22
|
+
# user.male? # => true
|
23
|
+
# user.female? # => false
|
24
|
+
#
|
25
|
+
# Using prefix:
|
26
|
+
#
|
27
|
+
# class User
|
28
|
+
# extend Enumerize
|
29
|
+
# enumerize :sex, in: %w(male female), predicates: { prefix: true }
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# user = User.new
|
33
|
+
# user.sex = 'female'
|
34
|
+
# user.sex_female? # => true
|
35
|
+
#
|
36
|
+
# Use <tt>only</tt> and <tt>except</tt> options to specify what values create
|
37
|
+
# predicate methods for.
|
38
|
+
module Predicates
|
39
|
+
def enumerize(name, options={})
|
40
|
+
super
|
41
|
+
|
42
|
+
if options[:predicates]
|
43
|
+
Builder.new(enumerized_attributes[name], options[:predicates]).build(_enumerize_module)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Builder
|
48
|
+
def initialize(attr, options)
|
49
|
+
@attr = attr
|
50
|
+
@options = options.is_a?(Hash) ? options : {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def values
|
54
|
+
values = @attr.values
|
55
|
+
|
56
|
+
if @options[:only]
|
57
|
+
values &= Array(@options[:only]).map(&:to_s)
|
58
|
+
end
|
59
|
+
|
60
|
+
if @options[:except]
|
61
|
+
values -= Array(@options[:except]).map(&:to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
values
|
65
|
+
end
|
66
|
+
|
67
|
+
def names
|
68
|
+
values.map { |v| "#{v.tr('-', '_')}?" }
|
69
|
+
end
|
70
|
+
|
71
|
+
def build(klass)
|
72
|
+
klass.delegate(*names, to: @attr.name, prefix: @options[:prefix], allow_nil: true)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Scope
|
5
|
+
module ActiveRecord
|
6
|
+
def enumerize(name, options={})
|
7
|
+
super
|
8
|
+
|
9
|
+
_enumerize_module.dependent_eval do
|
10
|
+
if self < ::ActiveRecord::Base
|
11
|
+
if options[:scope]
|
12
|
+
_define_activerecord_scope_methods!(name, options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def _define_activerecord_scope_methods!(name, options)
|
21
|
+
return _define_activerecord_shallow_scopes!(name) if options[:scope] == :shallow
|
22
|
+
|
23
|
+
scope_name = options[:scope] == true ? "with_#{name}" : options[:scope]
|
24
|
+
|
25
|
+
define_singleton_method scope_name do |*values|
|
26
|
+
values = enumerized_attributes[name].find_values(*values).map(&:value)
|
27
|
+
values = values.first if values.size == 1
|
28
|
+
|
29
|
+
where(name => values)
|
30
|
+
end
|
31
|
+
|
32
|
+
if options[:scope] == true
|
33
|
+
define_singleton_method "without_#{name}" do |*values|
|
34
|
+
values = enumerized_attributes[name].find_values(*values).map(&:value)
|
35
|
+
where(arel_table[name].not_in(values))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def _define_activerecord_shallow_scopes!(attribute_name)
|
41
|
+
enumerized_attributes[attribute_name].each_value do |value_obj|
|
42
|
+
define_singleton_method(value_obj) do
|
43
|
+
where(attribute_name => value_obj.value)
|
44
|
+
end
|
45
|
+
|
46
|
+
define_singleton_method("not_#{value_obj}") do
|
47
|
+
where.not(attribute_name => value_obj.value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Scope
|
5
|
+
module Mongoid
|
6
|
+
def enumerize(name, options={})
|
7
|
+
super
|
8
|
+
|
9
|
+
_enumerize_module.dependent_eval do
|
10
|
+
if self < ::Mongoid::Document
|
11
|
+
if options[:scope]
|
12
|
+
_define_mongoid_scope_methods!(name, options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def _define_mongoid_scope_methods!(name, options)
|
21
|
+
return _define_mongoid_shallow_scopes!(name) if options[:scope] == :shallow
|
22
|
+
scope_name = options[:scope] == true ? "with_#{name}" : options[:scope]
|
23
|
+
|
24
|
+
define_singleton_method scope_name do |*values|
|
25
|
+
values = enumerized_attributes[name].find_values(*values).map(&:value)
|
26
|
+
self.in(name => values)
|
27
|
+
end
|
28
|
+
|
29
|
+
if options[:scope] == true
|
30
|
+
define_singleton_method "without_#{name}" do |*values|
|
31
|
+
values = enumerized_attributes[name].find_values(*values).map(&:value)
|
32
|
+
not_in(name => values)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def _define_mongoid_shallow_scopes!(attribute_name)
|
38
|
+
enumerized_attributes[attribute_name].each_value do |value_obj|
|
39
|
+
define_singleton_method(value_obj) do
|
40
|
+
self.in(attribute_name => value_obj.value)
|
41
|
+
end
|
42
|
+
|
43
|
+
define_singleton_method("not_#{value_obj}") do
|
44
|
+
self.not_in(attribute_name => value_obj.value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Scope
|
5
|
+
module Sequel
|
6
|
+
def enumerize(name, options={})
|
7
|
+
super
|
8
|
+
|
9
|
+
_enumerize_module.dependent_eval do
|
10
|
+
if defined?(::Sequel::Model) && self < ::Sequel::Model
|
11
|
+
if options[:scope]
|
12
|
+
_define_sequel_scope_methods!(name, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'enumerize/hooks/sequel_dataset'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _define_sequel_scope_methods!(name, options)
|
23
|
+
return _define_sequel_shallow_scopes!(name) if options[:scope] == :shallow
|
24
|
+
|
25
|
+
klass = self
|
26
|
+
scope_name = options[:scope] == true ? "with_#{name}" : options[:scope]
|
27
|
+
|
28
|
+
def_dataset_method scope_name do |*values|
|
29
|
+
values = values.map { |value| klass.enumerized_attributes[name].find_value(value).value }
|
30
|
+
values = values.first if values.size == 1
|
31
|
+
|
32
|
+
where(name => values)
|
33
|
+
end
|
34
|
+
|
35
|
+
if options[:scope] == true
|
36
|
+
def_dataset_method "without_#{name}" do |*values|
|
37
|
+
values = values.map { |value| klass.enumerized_attributes[name].find_value(value).value }
|
38
|
+
exclude(name => values)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def _define_sequel_shallow_scopes!(attribute_name)
|
44
|
+
enumerized_attributes[attribute_name].each_value do |value_obj|
|
45
|
+
def_dataset_method(value_obj) do
|
46
|
+
where(attribute_name => value_obj.value.to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
def_dataset_method("not_#{value_obj}") do
|
50
|
+
exclude(attribute_name => value_obj.value.to_s)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module SequelSupport
|
5
|
+
def enumerize(name, options={})
|
6
|
+
super
|
7
|
+
|
8
|
+
_enumerize_module.dependent_eval do
|
9
|
+
if defined?(::Sequel::Model) && self < ::Sequel::Model
|
10
|
+
include InstanceMethods
|
11
|
+
|
12
|
+
require 'enumerize/hooks/sequel_dataset'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def validate
|
21
|
+
super
|
22
|
+
|
23
|
+
self.class.enumerized_attributes.each do |attr|
|
24
|
+
skip_validations = Utils.call_if_callable(attr.skip_validations_value, self)
|
25
|
+
next if skip_validations
|
26
|
+
|
27
|
+
value = read_attribute_for_validation(attr.name)
|
28
|
+
next if value.blank?
|
29
|
+
|
30
|
+
if attr.kind_of? Multiple
|
31
|
+
errors.add attr.name, "is invalid" unless value.respond_to?(:all?) && value.all? { |v| v.blank? || attr.find_value(v) }
|
32
|
+
else
|
33
|
+
errors.add attr.name, "is not included in the list" unless attr.find_value(value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def _set_default_value_for_enumerized_attributes
|
39
|
+
_enumerized_values_for_validation.delete_if do |k, v|
|
40
|
+
v.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
if defined?(Sequel::Plugins::Serialization::InstanceMethods)
|
44
|
+
modules = self.class.ancestors
|
45
|
+
plugin_idx = modules.index(Sequel::Plugins::Serialization::InstanceMethods)
|
46
|
+
|
47
|
+
if plugin_idx && plugin_idx < modules.index(Enumerize::SequelSupport::InstanceMethods)
|
48
|
+
abort "ERROR: You need to enable the Sequel serialization plugin before calling any enumerize methods on a model."
|
49
|
+
end
|
50
|
+
|
51
|
+
plugin_idx = modules.index(Sequel::Plugins::ValidationHelpers::InstanceMethods)
|
52
|
+
|
53
|
+
if plugin_idx && plugin_idx < modules.index(Enumerize::SequelSupport::InstanceMethods)
|
54
|
+
abort "ERROR: You need to enable the Sequel validation_helpers plugin before calling any enumerize methods on a model."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
|
5
|
+
module Enumerize
|
6
|
+
class Set
|
7
|
+
include Enumerable
|
8
|
+
include Predicatable
|
9
|
+
|
10
|
+
attr_reader :values
|
11
|
+
|
12
|
+
def initialize(obj, attr, values)
|
13
|
+
@obj = obj
|
14
|
+
@attr = attr
|
15
|
+
@values = []
|
16
|
+
|
17
|
+
if values.respond_to?(:each)
|
18
|
+
values.each do |input|
|
19
|
+
value = @attr.find_value(input)
|
20
|
+
|
21
|
+
if value && !@values.include?(value)
|
22
|
+
@values << value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def <<(value)
|
29
|
+
@values << value
|
30
|
+
mutate!
|
31
|
+
end
|
32
|
+
|
33
|
+
alias_method :push, :<<
|
34
|
+
|
35
|
+
delegate :each, :empty?, :size, to: :values
|
36
|
+
|
37
|
+
def to_ary
|
38
|
+
@values.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
def texts
|
42
|
+
@values.map(&:text)
|
43
|
+
end
|
44
|
+
|
45
|
+
delegate :join, to: :to_ary
|
46
|
+
|
47
|
+
def ==(other)
|
48
|
+
return false unless other.respond_to?(:each)
|
49
|
+
other.size == size && other.all? { |v| @values.include?(@attr.find_value(v)) }
|
50
|
+
end
|
51
|
+
|
52
|
+
alias_method :eql?, :==
|
53
|
+
|
54
|
+
def include?(value)
|
55
|
+
@values.include?(@attr.find_value(value))
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete(value)
|
59
|
+
@values.delete(@attr.find_value(value))
|
60
|
+
mutate!
|
61
|
+
end
|
62
|
+
|
63
|
+
def inspect
|
64
|
+
"#<Enumerize::Set {#{join(', ')}}>"
|
65
|
+
end
|
66
|
+
|
67
|
+
def encode_with(coder)
|
68
|
+
coder.represent_object(Array, @values)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def predicate_call(value)
|
74
|
+
include?(value)
|
75
|
+
end
|
76
|
+
|
77
|
+
def mutate!
|
78
|
+
@values = @obj.public_send("#{@attr.name}=", @values).values
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|