enumerize 0.3.0 → 2.3.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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -1
  3. data/.rspec +2 -0
  4. data/.travis.yml +38 -11
  5. data/CHANGELOG.md +258 -0
  6. data/Gemfile +5 -11
  7. data/Gemfile.global +20 -0
  8. data/Gemfile.mongo_mapper +7 -0
  9. data/Gemfile.rails42 +7 -0
  10. data/Gemfile.rails50 +7 -0
  11. data/Gemfile.rails52 +7 -0
  12. data/README.md +405 -17
  13. data/Rakefile +7 -1
  14. data/enumerize.gemspec +6 -3
  15. data/lib/enumerize/activemodel.rb +47 -0
  16. data/lib/enumerize/activerecord.rb +127 -2
  17. data/lib/enumerize/attribute.rb +167 -7
  18. data/lib/enumerize/attribute_map.rb +4 -0
  19. data/lib/enumerize/base.rb +60 -61
  20. data/lib/enumerize/hooks/formtastic.rb +11 -12
  21. data/lib/enumerize/hooks/sequel_dataset.rb +17 -0
  22. data/lib/enumerize/hooks/simple_form.rb +21 -8
  23. data/lib/enumerize/hooks/uniqueness.rb +22 -0
  24. data/lib/enumerize/integrations/rails_admin.rb +18 -0
  25. data/lib/enumerize/integrations/rspec/matcher.rb +161 -0
  26. data/lib/enumerize/integrations/rspec.rb +19 -0
  27. data/lib/enumerize/module.rb +33 -0
  28. data/lib/enumerize/module_attributes.rb +3 -2
  29. data/lib/enumerize/mongoid.rb +29 -0
  30. data/lib/enumerize/predicatable.rb +23 -0
  31. data/lib/enumerize/predicates.rb +76 -0
  32. data/lib/enumerize/scope/activerecord.rb +49 -0
  33. data/lib/enumerize/scope/mongoid.rb +46 -0
  34. data/lib/enumerize/scope/sequel.rb +52 -0
  35. data/lib/enumerize/sequel.rb +62 -0
  36. data/lib/enumerize/set.rb +81 -0
  37. data/lib/enumerize/utils.rb +12 -0
  38. data/lib/enumerize/value.rb +19 -46
  39. data/lib/enumerize/version.rb +3 -1
  40. data/lib/enumerize.rb +56 -4
  41. data/lib/sequel/plugins/enumerize.rb +18 -0
  42. data/spec/enumerize/integrations/rspec/matcher_spec.rb +260 -0
  43. data/spec/spec_helper.rb +30 -0
  44. data/test/activemodel_test.rb +114 -0
  45. data/test/activerecord_test.rb +542 -8
  46. data/test/attribute_map_test.rb +2 -0
  47. data/test/attribute_test.rb +102 -4
  48. data/test/base_test.rb +61 -39
  49. data/test/formtastic_test.rb +102 -17
  50. data/test/module_attributes_test.rb +25 -2
  51. data/test/mongo_mapper_test.rb +84 -0
  52. data/test/mongoid_test.rb +98 -7
  53. data/test/multiple_test.rb +59 -0
  54. data/test/predicates_test.rb +65 -0
  55. data/test/rails_admin_test.rb +27 -0
  56. data/test/sequel_test.rb +341 -0
  57. data/test/set_test.rb +166 -0
  58. data/test/simple_form_test.rb +110 -4
  59. data/test/support/mock_controller.rb +11 -1
  60. data/test/support/shared_enums.rb +43 -0
  61. data/test/support/view_test_helper.rb +6 -0
  62. data/test/test_helper.rb +25 -6
  63. data/test/value_test.rb +102 -13
  64. metadata +62 -28
  65. data/gemfiles/Gemfile-ar-3.1.x +0 -13
@@ -1,7 +1,132 @@
1
- require 'active_support/concern'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Enumerize
4
- module ActiveRecord
4
+ module ActiveRecordSupport
5
+ def enumerize(name, options={})
6
+ super
5
7
 
8
+ _enumerize_module.dependent_eval do
9
+ if self < ::ActiveRecord::Base
10
+ include InstanceMethods
11
+
12
+ const_get(:ActiveRecord_Relation).include(RelationMethods)
13
+ const_get(:ActiveRecord_AssociationRelation).include(RelationMethods)
14
+ const_get(:ActiveRecord_Associations_CollectionProxy).include(RelationMethods)
15
+
16
+ # Since Rails use `allocate` method on models and initializes them with `init_with` method.
17
+ # This way `initialize` method is not being called, but `after_initialize` callback always gets triggered.
18
+ after_initialize :_set_default_value_for_enumerized_attributes
19
+
20
+ # https://github.com/brainspec/enumerize/issues/111
21
+ require 'enumerize/hooks/uniqueness'
22
+
23
+ unless options[:multiple]
24
+ decorate_attribute_type(name, :enumerize) do |subtype|
25
+ Type.new(enumerized_attributes[name], subtype)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ # https://github.com/brainspec/enumerize/issues/74
34
+ def write_attribute(attr_name, value, *options)
35
+ if self.class.enumerized_attributes[attr_name]
36
+ _enumerized_values_for_validation[attr_name.to_s] = value
37
+ end
38
+
39
+ super
40
+ end
41
+
42
+ # Support multiple enumerized attributes
43
+ def becomes(klass)
44
+ became = super
45
+ klass.enumerized_attributes.each do |attr|
46
+ # Rescue when column associated to the enum does not exist.
47
+ begin
48
+ became.send("#{attr.name}=", send(attr.name))
49
+ rescue ActiveModel::MissingAttributeError
50
+ end
51
+ end
52
+
53
+ became
54
+ end
55
+
56
+ def reload(options = nil)
57
+ reloaded = super
58
+
59
+ reloaded.class.enumerized_attributes.each do |attr|
60
+ begin
61
+ # Checks first if the enumerized attribute is in ActiveRecord::Store
62
+ store_attr, _ = reloaded.class.stored_attributes.detect do |store_attr, keys|
63
+ keys.include?(attr.name)
64
+ end
65
+
66
+ if store_attr.present?
67
+ reloaded.send("#{attr.name}=", reloaded.send(store_attr).with_indifferent_access[attr.name])
68
+ else
69
+ reloaded.send("#{attr.name}=", reloaded[attr.name])
70
+ end
71
+ rescue ActiveModel::MissingAttributeError
72
+ end
73
+ end
74
+
75
+ reloaded
76
+ end
77
+ end
78
+
79
+ module RelationMethods
80
+ def update_all(updates)
81
+ if updates.is_a?(Hash)
82
+ enumerized_attributes.each do |attr|
83
+ next if updates[attr.name].blank? || attr.kind_of?(Enumerize::Multiple)
84
+ enumerize_value = attr.find_value(updates[attr.name])
85
+ updates[attr.name] = enumerize_value && enumerize_value.value
86
+ end
87
+ end
88
+
89
+ super(updates)
90
+ end
91
+ end
92
+
93
+ class Type < ActiveRecord::Type::Value
94
+ delegate :type, to: :@subtype
95
+
96
+ def initialize(attr, subtype)
97
+ @attr = attr
98
+ @subtype = subtype
99
+ end
100
+
101
+ def serialize(value)
102
+ v = @attr.find_value(value)
103
+ (v && v.value) || value
104
+ end
105
+
106
+ alias type_cast_for_database serialize
107
+
108
+ def deserialize(value)
109
+ @attr.find_value(value)
110
+ end
111
+
112
+ alias type_cast_from_database deserialize
113
+
114
+ def as_json(options = nil)
115
+ {attr: @attr.name, subtype: @subtype}.as_json(options)
116
+ end
117
+
118
+ def encode_with(coder)
119
+ coder[:class_name] = @attr.klass.name
120
+ coder[:attr_name] = @attr.name
121
+ coder[:subtype] = @subtype
122
+ end
123
+
124
+ def init_with(coder)
125
+ initialize(
126
+ coder[:class_name].constantize.enumerized_attributes[coder[:attr_name]],
127
+ coder[:subtype]
128
+ )
129
+ end
130
+ end
6
131
  end
7
132
  end
@@ -1,32 +1,192 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerize
2
4
  class Attribute
3
- attr_reader :name, :values, :default_value
5
+ attr_reader :klass, :name, :values, :default_value, :i18n_scope, :skip_validations_value
4
6
 
5
7
  def initialize(klass, name, options={})
6
8
  raise ArgumentError, ':in option is required' unless options[:in]
9
+ raise ArgumentError, ':scope option does not work with option :multiple' if options[:multiple] && options[:scope]
10
+
11
+ extend Multiple if options[:multiple]
7
12
 
8
13
  @klass = klass
9
14
  @name = name.to_sym
10
- @values = Array(options[:in]).map { |v| Value.new(self, *v) }
15
+
16
+ if options[:i18n_scope]
17
+ raise ArgumentError, ':i18n_scope option accepts only String or Array of strings' unless Array(options[:i18n_scope]).all? { |s| s.is_a?(String) }
18
+ @i18n_scope = options[:i18n_scope]
19
+ end
20
+
21
+ value_class = options.fetch(:value_class, Value)
22
+ @values = Array(options[:in]).map { |v| value_class.new(self, *v).freeze }
23
+
11
24
  @value_hash = Hash[@values.map { |v| [v.value.to_s, v] }]
12
25
  @value_hash.merge! Hash[@values.map { |v| [v.to_s, v] }]
13
26
 
14
27
  if options[:default]
15
- @default_value = find_value(options[:default])
28
+ @default_value = find_default_value(options[:default])
16
29
  raise ArgumentError, 'invalid default value' unless @default_value
17
30
  end
31
+
32
+ @skip_validations_value = options.fetch(:skip_validations, false)
33
+ end
34
+
35
+ def find_default_value(value)
36
+ if value.respond_to?(:call)
37
+ value
38
+ else
39
+ find_value(value)
40
+ end
18
41
  end
19
42
 
20
43
  def find_value(value)
21
44
  @value_hash[value.to_s] unless value.nil?
22
45
  end
23
46
 
24
- def i18n_suffix
25
- @klass.model_name.i18n_key if @klass.respond_to?(:model_name)
47
+ def find_values(*values)
48
+ values.map { |value| find_value(value) }.compact
49
+ end
50
+
51
+ def each_value
52
+ values.each { |value| yield value }
53
+ end
54
+
55
+ def i18n_scopes
56
+ @i18n_scopes ||= if i18n_scope
57
+ Array(i18n_scope)
58
+ elsif @klass.respond_to?(:model_name)
59
+ ["enumerize.#{@klass.model_name.i18n_key}.#{name}"]
60
+ else
61
+ []
62
+ end
63
+ end
64
+
65
+ def options(options = {})
66
+ values = if options.empty?
67
+ @values
68
+ else
69
+ raise ArgumentError, 'Options cannot have both :only and :except' if options[:only] && options[:except]
70
+
71
+ only = Array(options[:only]).map(&:to_s)
72
+ except = Array(options[:except]).map(&:to_s)
73
+
74
+ @values.reject do |value|
75
+ if options[:only]
76
+ !only.include?(value)
77
+ elsif options[:except]
78
+ except.include?(value)
79
+ end
80
+ end
81
+ end
82
+
83
+ values.map { |v| [v.text, v.to_s] }
84
+ end
85
+
86
+ def respond_to_missing?(method, include_private=false)
87
+ @value_hash.include?(method.to_s) || super
88
+ end
89
+
90
+ def define_methods!(mod)
91
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
92
+ def #{name}
93
+ if defined?(super)
94
+ self.class.enumerized_attributes[:#{name}].find_value(super)
95
+ elsif respond_to?(:read_attribute)
96
+ self.class.enumerized_attributes[:#{name}].find_value(read_attribute(:#{name}))
97
+ else
98
+ if defined?(@#{name})
99
+ self.class.enumerized_attributes[:#{name}].find_value(@#{name})
100
+ else
101
+ @#{name} = nil
102
+ end
103
+ end
104
+ end
105
+
106
+ def #{name}=(new_value)
107
+ allowed_value_or_nil = self.class.enumerized_attributes[:#{name}].find_value(new_value)
108
+ allowed_value_or_nil = allowed_value_or_nil.value unless allowed_value_or_nil.nil?
109
+
110
+ if defined?(super)
111
+ super allowed_value_or_nil
112
+ elsif respond_to?(:write_attribute, true)
113
+ write_attribute '#{name}', allowed_value_or_nil
114
+ else
115
+ @#{name} = allowed_value_or_nil
116
+ end
117
+
118
+ _enumerized_values_for_validation['#{name}'] = new_value.nil? ? nil : new_value.to_s
119
+
120
+ allowed_value_or_nil
121
+ end
122
+
123
+ def #{name}_text
124
+ self.#{name} && self.#{name}.text
125
+ end
126
+
127
+ def #{name}_value
128
+ self.#{name} && self.#{name}.value
129
+ end
130
+ RUBY
131
+ end
132
+
133
+ private
134
+
135
+ def method_missing(method)
136
+ if @value_hash.include?(method.to_s)
137
+ find_value(method)
138
+ else
139
+ super
140
+ end
141
+ end
142
+ end
143
+
144
+ module Multiple
145
+ def find_default_value(value)
146
+ if value.respond_to?(:call)
147
+ value
148
+ else
149
+ find_values(*value)
150
+ end
26
151
  end
27
152
 
28
- def options
29
- @values.map { |v| [v.text, v.to_s] }
153
+ def define_methods!(mod)
154
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
155
+ def #{name}
156
+ unless defined?(@_#{name}_enumerized_set)
157
+ if defined?(super)
158
+ self.#{name} = super
159
+ elsif respond_to?(:read_attribute)
160
+ self.#{name} = read_attribute(:#{name})
161
+ else
162
+ if defined?(@#{name})
163
+ self.#{name} = @#{name}
164
+ else
165
+ self.#{name} = []
166
+ end
167
+ end
168
+ end
169
+
170
+ @_#{name}_enumerized_set
171
+ end
172
+
173
+ def #{name}=(values)
174
+ @_#{name}_enumerized_set = Enumerize::Set.new(self, self.class.enumerized_attributes[:#{name}], values)
175
+ raw_values = #{name}.values.map(&:value)
176
+
177
+ if defined?(super)
178
+ super raw_values
179
+ elsif respond_to?(:write_attribute, true)
180
+ write_attribute '#{name}', raw_values
181
+ else
182
+ @#{name} = raw_values
183
+ end
184
+
185
+ _enumerized_values_for_validation['#{name}'] = values.respond_to?(:map) ? values.reject(&:blank?).map(&:to_s) : values
186
+
187
+ #{name}
188
+ end
189
+ RUBY
30
190
  end
31
191
  end
32
192
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerize
2
4
  class AttributeMap
5
+ attr_reader :attributes
6
+
3
7
  def initialize
4
8
  @attributes = {}
5
9
  @dependants = []
@@ -1,8 +1,15 @@
1
- require 'active_support/concern'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Enumerize
4
4
  module Base
5
- extend ActiveSupport::Concern
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.singleton_class.prepend ClassMethods::Hook
8
+
9
+ if base.respond_to?(:validate)
10
+ base.validate :_validate_enumerized_attributes
11
+ end
12
+ end
6
13
 
7
14
  module ClassMethods
8
15
  def enumerize(name, options={})
@@ -17,90 +24,45 @@ module Enumerize
17
24
  RUBY
18
25
  end
19
26
 
20
- _define_enumerize_attribute(attr)
21
-
22
- _enumerize_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
23
- def #{attr.name}_text
24
- #{attr.name} && #{attr.name}.text
25
- end
26
- RUBY
27
-
28
- if respond_to?(:validates)
29
- validates name, :inclusion => {:in => enumerized_attributes[name].values.map(&:to_s), :allow_nil => true, :allow_blank => true}
30
- end
27
+ attr.define_methods!(_enumerize_module)
31
28
  end
32
29
 
33
30
  def enumerized_attributes
34
31
  @enumerized_attributes ||= AttributeMap.new
35
32
  end
36
33
 
37
- def inherited(subclass)
38
- enumerized_attributes.add_dependant subclass.enumerized_attributes
39
- super
34
+ module Hook
35
+ def inherited(subclass)
36
+ enumerized_attributes.add_dependant subclass.enumerized_attributes
37
+ super subclass
38
+ end
40
39
  end
41
40
 
42
41
  private
43
42
 
44
43
  def _enumerize_module
45
44
  @_enumerize_module ||= begin
46
- mod = Module.new do
47
- @_class_methods = Module.new
48
- class << self
49
- attr_reader :_class_methods
50
- end
51
- end
45
+ mod = Module.new
52
46
  include mod
53
- extend mod._class_methods
54
47
  mod
55
48
  end
56
49
  end
57
-
58
- def _define_enumerize_attribute(attr)
59
- _enumerize_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
60
- def #{attr.name}
61
- if defined?(super)
62
- self.class.enumerized_attributes[:#{attr.name}].find_value(super)
63
- elsif respond_to?(:read_attribute, true)
64
- self.class.enumerized_attributes[:#{attr.name}].find_value(read_attribute(:#{attr.name}))
65
- else
66
- if defined?(@#{attr.name})
67
- self.class.enumerized_attributes[:#{attr.name}].find_value(@#{attr.name})
68
- else
69
- @#{attr.name} = nil
70
- end
71
- end
72
- end
73
-
74
- def #{attr.name}=(new_value)
75
- _enumerized_values_for_validation[:#{attr.name}] = new_value.nil? ? nil : new_value.to_s
76
-
77
- allowed_value_or_nil = self.class.enumerized_attributes[:#{attr.name}].find_value(new_value)
78
- allowed_value_or_nil = allowed_value_or_nil.value unless allowed_value_or_nil.nil?
79
-
80
- if defined?(super)
81
- super allowed_value_or_nil
82
- elsif respond_to?(:write_attribute, true)
83
- write_attribute :#{attr.name}, allowed_value_or_nil
84
- else
85
- @#{attr.name} = allowed_value_or_nil
86
- end
87
- end
88
- RUBY
89
- end
90
50
  end
91
51
 
92
52
  def initialize(*)
93
53
  super
94
- self.class.enumerized_attributes.each do |attr|
95
- public_send("#{attr.name}=", attr.default_value) unless _enumerized_values_for_validation.key?(attr.name)
96
- end
54
+ _set_default_value_for_enumerized_attributes
97
55
  end
98
56
 
99
57
  def read_attribute_for_validation(key)
100
- if self.class.enumerized_attributes[key].instance_of?(Enumerize::Attribute) && _enumerized_values_for_validation.has_key?(key)
58
+ key = key.to_s
59
+
60
+ if _enumerized_values_for_validation.has_key?(key)
101
61
  _enumerized_values_for_validation[key]
102
- else
62
+ elsif defined?(super)
103
63
  super
64
+ else
65
+ send(key)
104
66
  end
105
67
  end
106
68
 
@@ -109,5 +71,42 @@ module Enumerize
109
71
  def _enumerized_values_for_validation
110
72
  @_enumerized_values_for_validation ||= {}
111
73
  end
74
+
75
+ def _validate_enumerized_attributes
76
+ self.class.enumerized_attributes.each do |attr|
77
+ skip_validations = Utils.call_if_callable(attr.skip_validations_value, self)
78
+ next if skip_validations
79
+
80
+ value = read_attribute_for_validation(attr.name)
81
+ next if value.blank?
82
+
83
+ if attr.kind_of? Multiple
84
+ errors.add attr.name unless value.respond_to?(:all?) && value.all? { |v| v.blank? || attr.find_value(v) }
85
+ else
86
+ errors.add attr.name, :inclusion unless attr.find_value(value)
87
+ end
88
+ end
89
+ end
90
+
91
+ def _set_default_value_for_enumerized_attributes
92
+ self.class.enumerized_attributes.each do |attr|
93
+ next if attr.default_value.nil?
94
+ begin
95
+ if respond_to?(attr.name)
96
+ attr_value = public_send(attr.name)
97
+ else
98
+ next
99
+ end
100
+
101
+ value_for_validation = _enumerized_values_for_validation[attr.name.to_s]
102
+
103
+ if (!attr_value || attr_value.empty?) && (!value_for_validation || value_for_validation.empty?)
104
+ value = Utils.call_if_callable(attr.default_value, self)
105
+ public_send("#{attr.name}=", value)
106
+ end
107
+ rescue ActiveModel::MissingAttributeError
108
+ end
109
+ end
110
+ end
112
111
  end
113
112
  end
@@ -1,28 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
2
4
 
3
5
  module Enumerize
4
6
  module Hooks
5
7
  module FormtasticFormBuilderExtension
6
- extend ActiveSupport::Concern
7
8
 
8
- included do
9
- alias_method_chain :input, :enumerize
10
- end
9
+ def input(method, options={})
10
+ enumerized_object = convert_to_model(object)
11
+ klass = enumerized_object.class
11
12
 
12
- def input_with_enumerize(method, options={})
13
- klass = object.class
14
13
  if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[method])
15
14
  options[:collection] ||= attr.options
15
+
16
+ if attr.kind_of?(Enumerize::Multiple) && options[:as] != :check_boxes
17
+ options[:input_html] = options.fetch(:input_html, {}).merge(:multiple => true)
18
+ end
16
19
  end
17
20
 
18
- input_without_enumerize(method, options)
21
+ super(method, options)
19
22
  end
20
23
  end
21
24
  end
22
25
  end
23
26
 
24
- if defined? ::Formtastic::SemanticFormBuilder
25
- ::Formtastic::SemanticFormBuilder.send :include, Enumerize::Hooks::FormtasticFormBuilderExtension
26
- else
27
- ::Formtastic::FormBuilder.send :include, Enumerize::Hooks::FormtasticFormBuilderExtension
28
- end
27
+ ::Formtastic::FormBuilder.send :prepend, Enumerize::Hooks::FormtasticFormBuilderExtension
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Enumerize
4
+ module Hooks
5
+ module SequelDataset
6
+ def literal_append(sql, v)
7
+ if v.is_a?(Enumerize::Value)
8
+ super(sql, v.value)
9
+ else
10
+ super(sql, v)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ ::Sequel::Dataset.send :prepend, Enumerize::Hooks::SequelDataset
@@ -1,24 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
2
4
 
3
5
  module Enumerize
4
6
  module Hooks
5
7
  module SimpleFormBuilderExtension
6
- extend ActiveSupport::Concern
7
8
 
8
- included do
9
- alias_method_chain :input, :enumerize
9
+ def input(attribute_name, options={}, &block)
10
+ add_input_options_for_enumerized_attribute(attribute_name, options)
11
+ super(attribute_name, options, &block)
12
+ end
13
+
14
+ def input_field(attribute_name, options={})
15
+ add_input_options_for_enumerized_attribute(attribute_name, options)
16
+ super(attribute_name, options)
10
17
  end
11
18
 
12
- def input_with_enumerize(attribute_name, options={}, &block)
13
- klass = object.class
19
+ private
20
+
21
+ def add_input_options_for_enumerized_attribute(attribute_name, options)
22
+ enumerized_object = convert_to_model(object)
23
+ klass = enumerized_object.class
24
+
14
25
  if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[attribute_name])
15
26
  options[:collection] ||= attr.options
16
- end
17
27
 
18
- input_without_enumerize(attribute_name, options, &block)
28
+ if attr.kind_of?(Enumerize::Multiple) && options[:as] != :check_boxes
29
+ options[:input_html] = options.fetch(:input_html, {}).merge(:multiple => true)
30
+ end
31
+ end
19
32
  end
20
33
  end
21
34
  end
22
35
  end
23
36
 
24
- ::SimpleForm::FormBuilder.send :include, Enumerize::Hooks::SimpleFormBuilderExtension
37
+ ::SimpleForm::FormBuilder.send :prepend, Enumerize::Hooks::SimpleFormBuilderExtension
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Enumerize
6
+ module Hooks
7
+ module UniquenessValidator
8
+
9
+ def validate_each(record, name, value)
10
+ klass = record.to_model.class
11
+
12
+ if klass.respond_to?(:enumerized_attributes) && (attr = klass.enumerized_attributes[name])
13
+ value = attr.find_value(value).try(:value)
14
+ end
15
+
16
+ super(record, name, value)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ ::ActiveRecord::Validations::UniquenessValidator.send :prepend, Enumerize::Hooks::UniquenessValidator
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Enumerize
4
+ module Integrations
5
+ module RailsAdmin
6
+
7
+ def enumerize(name, options={})
8
+ super
9
+
10
+ _enumerize_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
11
+ def #{name}_enum
12
+ self.class.enumerized_attributes[:#{name}].options
13
+ end
14
+ RUBY
15
+ end
16
+ end
17
+ end
18
+ end