enumerize 0.3.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -1
- data/.rspec +2 -0
- data/.travis.yml +38 -11
- data/CHANGELOG.md +258 -0
- data/Gemfile +5 -11
- data/Gemfile.global +20 -0
- data/Gemfile.mongo_mapper +7 -0
- data/Gemfile.rails42 +7 -0
- data/Gemfile.rails50 +7 -0
- data/Gemfile.rails52 +7 -0
- data/README.md +405 -17
- data/Rakefile +7 -1
- data/enumerize.gemspec +6 -3
- data/lib/enumerize/activemodel.rb +47 -0
- data/lib/enumerize/activerecord.rb +127 -2
- data/lib/enumerize/attribute.rb +167 -7
- data/lib/enumerize/attribute_map.rb +4 -0
- data/lib/enumerize/base.rb +60 -61
- data/lib/enumerize/hooks/formtastic.rb +11 -12
- data/lib/enumerize/hooks/sequel_dataset.rb +17 -0
- data/lib/enumerize/hooks/simple_form.rb +21 -8
- data/lib/enumerize/hooks/uniqueness.rb +22 -0
- data/lib/enumerize/integrations/rails_admin.rb +18 -0
- data/lib/enumerize/integrations/rspec/matcher.rb +161 -0
- data/lib/enumerize/integrations/rspec.rb +19 -0
- data/lib/enumerize/module.rb +33 -0
- data/lib/enumerize/module_attributes.rb +3 -2
- 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 +49 -0
- data/lib/enumerize/scope/mongoid.rb +46 -0
- data/lib/enumerize/scope/sequel.rb +52 -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 +19 -46
- data/lib/enumerize/version.rb +3 -1
- data/lib/enumerize.rb +56 -4
- data/lib/sequel/plugins/enumerize.rb +18 -0
- data/spec/enumerize/integrations/rspec/matcher_spec.rb +260 -0
- data/spec/spec_helper.rb +30 -0
- data/test/activemodel_test.rb +114 -0
- data/test/activerecord_test.rb +542 -8
- data/test/attribute_map_test.rb +2 -0
- data/test/attribute_test.rb +102 -4
- data/test/base_test.rb +61 -39
- data/test/formtastic_test.rb +102 -17
- data/test/module_attributes_test.rb +25 -2
- data/test/mongo_mapper_test.rb +84 -0
- data/test/mongoid_test.rb +98 -7
- data/test/multiple_test.rb +59 -0
- data/test/predicates_test.rb +65 -0
- data/test/rails_admin_test.rb +27 -0
- data/test/sequel_test.rb +341 -0
- data/test/set_test.rb +166 -0
- data/test/simple_form_test.rb +110 -4
- data/test/support/mock_controller.rb +11 -1
- data/test/support/shared_enums.rb +43 -0
- data/test/support/view_test_helper.rb +6 -0
- data/test/test_helper.rb +25 -6
- data/test/value_test.rb +102 -13
- metadata +62 -28
- data/gemfiles/Gemfile-ar-3.1.x +0 -13
@@ -0,0 +1,161 @@
|
|
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?("#{sorted_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
|
+
if expected_scope.is_a?(TrueClass)
|
125
|
+
subject_class.respond_to?("with_#{expected_attr}")
|
126
|
+
else
|
127
|
+
subject_class.respond_to?(expected_scope[:scope])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def sorted_values
|
132
|
+
@sorted_values ||=expected_values.map(&:to_s).sort
|
133
|
+
end
|
134
|
+
|
135
|
+
def enumerized_values
|
136
|
+
@enumerized_values ||= attributes.values.sort
|
137
|
+
end
|
138
|
+
|
139
|
+
def enumerized_default
|
140
|
+
@enumerized_default ||= attributes.default_value
|
141
|
+
end
|
142
|
+
|
143
|
+
def enumerized_value_hash
|
144
|
+
@enumerized_value_hash ||= attributes.instance_variable_get('@value_hash')
|
145
|
+
end
|
146
|
+
|
147
|
+
def attributes
|
148
|
+
subject_class.enumerized_attributes.attributes[expected_attr.to_s]
|
149
|
+
end
|
150
|
+
|
151
|
+
def subject_class
|
152
|
+
@subject_class ||= subject.class
|
153
|
+
end
|
154
|
+
|
155
|
+
def quote_values(values)
|
156
|
+
sorted_values.map(&:inspect).join(', ')
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
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
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Enumerize
|
2
4
|
module ModuleAttributes
|
3
5
|
def included(base)
|
4
|
-
base.
|
6
|
+
base.extend Enumerize
|
5
7
|
base.send :include, _enumerize_module
|
6
|
-
base.extend _enumerize_module._class_methods
|
7
8
|
enumerized_attributes.add_dependant base.enumerized_attributes
|
8
9
|
super
|
9
10
|
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.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,49 @@
|
|
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
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
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
|