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,69 +1,42 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'i18n'
2
4
 
3
5
  module Enumerize
4
6
  class Value < String
7
+ include Predicatable
8
+
9
+ attr_reader :value
10
+
5
11
  def initialize(attr, name, value=nil)
6
12
  @attr = attr
7
- @value = value || name.to_s
13
+ @value = value.nil? ? name.to_s : value
8
14
 
9
15
  super(name.to_s)
10
- end
11
16
 
12
- def value
13
- @value
17
+ @i18n_keys = @attr.i18n_scopes.map { |s| :"#{s}.#{self}" }
18
+ @i18n_keys << :"enumerize.defaults.#{@attr.name}.#{self}"
19
+ @i18n_keys << :"enumerize.#{@attr.name}.#{self}"
20
+ @i18n_keys << self.underscore.humanize # humanize value if there are no translations
21
+ @i18n_keys
14
22
  end
15
23
 
16
24
  def text
17
- I18n.t(i18n_keys[0], :default => i18n_keys[1..-1])
25
+ I18n.t(@i18n_keys[0], :default => @i18n_keys[1..-1])
18
26
  end
19
27
 
20
- def method_missing(method, *args, &block)
21
- if method[-1] == '?' && @attr.values.include?(method[0..-2])
22
- define_query_methods
23
- send(method, *args, &block)
24
- else
25
- super
26
- end
28
+ def ==(other)
29
+ super(other.to_s) || value == other
27
30
  end
28
31
 
29
- def respond_to?(method, include_private=false)
30
- if super
31
- true
32
- elsif method[-1] == '?' && @attr.values.include?(method[0..-2])
33
- define_query_methods
34
- super
35
- end
32
+ def encode_with(coder)
33
+ coder.represent_object(self.class.superclass, @value)
36
34
  end
37
35
 
38
36
  private
39
37
 
40
- def define_query_methods
41
- @attr.values.each do |value|
42
- unless singleton_methods.include?(:"#{value}?")
43
- singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
44
- def #{value}?
45
- #{value == self}
46
- end
47
- RUBY
48
- end
49
- end
50
- end
51
-
52
- def i18n_keys
53
- @i18n_keys ||= begin
54
- i18n_keys = []
55
- i18n_keys << i18n_scope
56
- i18n_keys << i18n_scope(i18n_suffix)
57
- i18n_keys << self.humanize # humanize value if there are no translations
58
- end
59
- end
60
-
61
- def i18n_scope(suffix = nil)
62
- :"enumerize.#{suffix}#{@attr.name}.#{self}"
63
- end
64
-
65
- def i18n_suffix
66
- "#{@attr.i18n_suffix}." if @attr.i18n_suffix
38
+ def predicate_call(value)
39
+ value == self
67
40
  end
68
41
  end
69
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerize
2
- VERSION = "0.3.0"
4
+ VERSION = '2.3.1'
3
5
  end
data/lib/enumerize.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
2
4
  require 'enumerize/version'
3
5
 
@@ -5,17 +7,59 @@ module Enumerize
5
7
  autoload :Attribute, 'enumerize/attribute'
6
8
  autoload :AttributeMap, 'enumerize/attribute_map'
7
9
  autoload :Value, 'enumerize/value'
10
+ autoload :Set, 'enumerize/set'
8
11
  autoload :Base, 'enumerize/base'
9
- autoload :ActiveRecord, 'enumerize/activerecord'
12
+ autoload :Module, 'enumerize/module'
13
+ autoload :Predicates, 'enumerize/predicates'
14
+ autoload :Predicatable, 'enumerize/predicatable'
15
+ autoload :Utils, 'enumerize/utils'
10
16
  autoload :ModuleAttributes, 'enumerize/module_attributes'
11
17
 
18
+ autoload :ActiveModelAttributesSupport, 'enumerize/activemodel'
19
+ autoload :ActiveRecordSupport, 'enumerize/activerecord'
20
+ autoload :SequelSupport, 'enumerize/sequel'
21
+ autoload :MongoidSupport, 'enumerize/mongoid'
22
+
23
+ module Scope
24
+ autoload :ActiveRecord, 'enumerize/scope/activerecord'
25
+ autoload :Sequel, 'enumerize/scope/sequel'
26
+ autoload :Mongoid, 'enumerize/scope/mongoid'
27
+ end
28
+
12
29
  def self.included(base)
30
+ ActiveSupport::Deprecation.warn '`include Enumerize` was deprecated. Please use `extend Enumerize`.', caller
31
+ extended(base)
32
+ end
33
+
34
+ def self.extended(base)
13
35
  base.send :include, Enumerize::Base
14
- if defined?(::ActiveRecord::Base) && base < ::ActiveRecord::Base
15
- base.extend Enumerize::ActiveRecord
36
+ base.extend Enumerize::Predicates
37
+
38
+ if defined?(::ActiveModel::Attributes)
39
+ base.extend Enumerize::ActiveModelAttributesSupport
16
40
  end
17
41
 
18
- if Module === base
42
+ if defined?(::ActiveRecord::Base)
43
+ base.extend Enumerize::ActiveRecordSupport
44
+ base.extend Enumerize::Scope::ActiveRecord
45
+ end
46
+
47
+ if defined?(::Mongoid::Document)
48
+ base.extend Enumerize::MongoidSupport
49
+ base.extend Enumerize::Scope::Mongoid
50
+ end
51
+
52
+ if defined?(::Sequel::Model)
53
+ base.extend Enumerize::SequelSupport
54
+ base.extend Enumerize::Scope::Sequel
55
+ end
56
+
57
+ if defined?(::RailsAdmin)
58
+ require 'enumerize/integrations/rails_admin'
59
+ base.extend Enumerize::Integrations::RailsAdmin
60
+ end
61
+
62
+ if ::Module === base
19
63
  base.extend Enumerize::Base::ClassMethods
20
64
  base.extend Enumerize::ModuleAttributes
21
65
  end
@@ -26,6 +70,7 @@ module Enumerize
26
70
  begin
27
71
  require 'simple_form'
28
72
  require 'enumerize/hooks/simple_form'
73
+ require 'enumerize/form_helper'
29
74
  rescue LoadError
30
75
  end
31
76
 
@@ -34,4 +79,11 @@ module Enumerize
34
79
  require 'enumerize/hooks/formtastic'
35
80
  rescue LoadError
36
81
  end
82
+
83
+ begin
84
+ require 'rspec/matchers'
85
+ rescue LoadError
86
+ else
87
+ require 'enumerize/integrations/rspec'
88
+ end
37
89
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequel
4
+ module Plugins
5
+ module Enumerize
6
+ # Depend on the def_dataset_method plugin
7
+ def self.apply(model)
8
+ model.plugin(:def_dataset_method) unless model.respond_to?(:def_dataset_method)
9
+ end
10
+
11
+ module InstanceMethods
12
+ def self.included(base)
13
+ base.extend ::Enumerize
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record'
4
+
5
+ silence_warnings do
6
+ ActiveRecord::Migration.verbose = false
7
+ ActiveRecord::Base.logger = Logger.new(nil)
8
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
+ end
10
+
11
+ ActiveRecord::Base.connection.instance_eval do
12
+ create_table :users do |t|
13
+ t.string :sex
14
+ t.string :role
15
+ t.string :account_type
16
+ end
17
+ end
18
+
19
+ class User < ActiveRecord::Base
20
+ extend Enumerize
21
+
22
+ enumerize :sex, :in => [:male, :female], scope: true
23
+ enumerize :role, :in => [:user, :admin], scope: :having_role
24
+ enumerize :account_type, :in => [:basic, :premium]
25
+ end
26
+
27
+ RSpec.describe Enumerize::Integrations::RSpec::Matcher do
28
+
29
+ let(:model) do
30
+ Class.new do
31
+ extend Enumerize
32
+
33
+ def self.name
34
+ 'Model'
35
+ end
36
+ end
37
+ end
38
+
39
+ subject do
40
+ model.new
41
+ end
42
+
43
+ describe 'without qualifier' do
44
+
45
+ it 'accepts when has defined a enumerize' do
46
+ model.enumerize(:sex, :in => [:male, :female])
47
+ expect(subject).to enumerize(:sex)
48
+ end
49
+
50
+ it 'rejects when has not defined a enumerize' do
51
+ message = 'Expected Model to define enumerize :sex'
52
+ expect do
53
+ expect(subject).to enumerize(:sex)
54
+ end.to fail_with(message)
55
+ end
56
+ end
57
+
58
+ describe '#in' do
59
+
60
+ context 'defined as array' do
61
+
62
+ before do
63
+ model.enumerize(:sex, :in => [:male, :female])
64
+ end
65
+
66
+ it 'accepts the right params as an array' do
67
+ expect(subject).to enumerize(:sex).in([:male, :female])
68
+ end
69
+
70
+ it 'accepts the right params as regular params' do
71
+ expect(subject).to enumerize(:sex).in(:male, :female)
72
+ end
73
+
74
+ it 'accepts the the right params in a different order' do
75
+ expect(subject).to enumerize(:sex).in(:female, :male)
76
+ end
77
+
78
+ it 'rejects wrong params' do
79
+ message = 'Expected Model to define enumerize :sex in: "boy", "girl"'
80
+ expect do
81
+ expect(subject).to enumerize(:sex).in(:boy, :girl)
82
+ end.to fail_with(message)
83
+ end
84
+
85
+ it 'has the right message when negated' do
86
+ message = 'Did not expect Model to define enumerize :sex in: "female", "male"'
87
+ expect do
88
+ expect(subject).to_not enumerize(:sex).in(:male, :female)
89
+ end.to fail_with(message)
90
+ end
91
+ end
92
+
93
+ context 'defined as hash' do
94
+
95
+ before do
96
+ model.enumerize(:sex, :in => { male: 0, female: 1 })
97
+ end
98
+
99
+ it 'accepts the right params as an array' do
100
+ expect(subject).to enumerize(:sex).in(:male, :female)
101
+ end
102
+
103
+ it 'accepts the right params as a hash' do
104
+ expect(subject).to enumerize(:sex).in(male: 0, female: 1)
105
+ end
106
+
107
+ it 'accepts the right params as a hash in a different order' do
108
+ expect(subject).to enumerize(:sex).in(female: 1, male: 0)
109
+ end
110
+
111
+ it 'rejects wrong keys' do
112
+ message = 'Expected Model to define enumerize :sex in: "{:boy=>0, :girl=>1}"'
113
+ expect do
114
+ expect(subject).to enumerize(:sex).in(boy: 0, girl: 1)
115
+ end.to fail_with(message)
116
+ end
117
+
118
+ it 'rejects wrong values' do
119
+ message = 'Expected Model to define enumerize :sex in: "{:male=>2, :female=>3}"'
120
+ expect do
121
+ expect(subject).to enumerize(:sex).in(male: 2, female: 3)
122
+ end.to fail_with(message)
123
+ end
124
+ end
125
+
126
+ it 'has the right description' do
127
+ matcher = enumerize(:sex).in(:male, :female)
128
+ expect(matcher.description).to eq('define enumerize :sex in: "female", "male"')
129
+ end
130
+ end
131
+
132
+ describe '#with_default' do
133
+
134
+ before do
135
+ model.enumerize(:sex, :in => [:male, :female], default: :female)
136
+ end
137
+
138
+ it 'accepts the right default value' do
139
+ expect(subject).to enumerize(:sex).in(:male, :female).with_default(:female)
140
+ end
141
+
142
+ it 'rejects the wrong default value' do
143
+ message = 'Expected Model to define enumerize :sex in: "female", "male" with "male" as default value'
144
+ expect do
145
+ expect(subject).to enumerize(:sex).in(:male, :female).with_default(:male)
146
+ end.to fail_with(message)
147
+ end
148
+
149
+ it 'rejects if the `in` is wrong with a correct default value' do
150
+ message = 'Expected Model to define enumerize :sex in: "boy", "girl" with "female" as default value'
151
+ expect do
152
+ expect(subject).to enumerize(:sex).in(:boy, :girl).with_default(:female)
153
+ end.to fail_with(message)
154
+ end
155
+
156
+ it 'has the right description' do
157
+ matcher = enumerize(:sex).in(:male, :female).with_default(:female)
158
+ message = 'define enumerize :sex in: "female", "male" with "female" as default value'
159
+ expect(matcher.description).to eq(message)
160
+ end
161
+ end
162
+
163
+ describe '#with_i18n_scope' do
164
+
165
+ context 'defined as string' do
166
+
167
+ before do
168
+ model.enumerize(:sex, :in => [:male, :female], i18n_scope: 'sex')
169
+ end
170
+
171
+ it 'accepts the right i18n_scope' do
172
+ expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope('sex')
173
+ end
174
+
175
+ it 'rejects the wrong i18n_scope' do
176
+ message = 'Expected Model to define enumerize :sex in: "female", "male" i18n_scope: "gender"'
177
+ expect do
178
+ expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope('gender')
179
+ end.to fail_with(message)
180
+ end
181
+ end
182
+
183
+ context 'defined as array' do
184
+
185
+ before do
186
+ model.enumerize(:sex, :in => [:male, :female], i18n_scope: ['sex', 'more.sex'])
187
+ end
188
+
189
+ it 'accepts the wrong i18n_scope' do
190
+ expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope(['sex', 'more.sex'])
191
+ end
192
+
193
+ it 'rejects the wrong i18n_scope' do
194
+ message = 'Expected Model to define enumerize :sex in: "female", "male" i18n_scope: ["sex"]'
195
+ expect do
196
+ expect(subject).to enumerize(:sex).in(:male, :female).with_i18n_scope(['sex'])
197
+ end.to fail_with(message)
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#with_predicates' do
203
+
204
+ it 'accepts when predicates is defined as a boolean' do
205
+ model.enumerize(:sex, :in => [:male, :female], predicates: true)
206
+ expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(true)
207
+ end
208
+
209
+ it 'accepts when predicates is defined as a hash' do
210
+ model.enumerize(:sex, :in => [:male, :female], predicates: { prefix: true })
211
+ expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(prefix: true)
212
+ end
213
+
214
+ it 'rejects when predicates is not defined' do
215
+ model.enumerize(:sex, :in => [:male, :female])
216
+ message = 'Expected Model to define enumerize :sex in: "female", "male" predicates: true'
217
+ expect do
218
+ expect(subject).to enumerize(:sex).in(:male, :female).with_predicates(true)
219
+ end.to fail_with(message)
220
+ end
221
+ end
222
+
223
+ describe '#with_multiple' do
224
+
225
+ it 'accepts when has defined the multiple' do
226
+ model.enumerize(:sex, :in => [:male, :female], multiple: true)
227
+ expect(subject).to enumerize(:sex).in(:male, :female).with_multiple(true)
228
+ end
229
+
230
+ it 'rejects when has not defined the multiple' do
231
+ model.enumerize(:sex, :in => [:male, :female])
232
+ message = 'Expected Model to define enumerize :sex in: "female", "male" multiple: true'
233
+ expect do
234
+ expect(subject).to enumerize(:sex).in(:male, :female).with_multiple(true)
235
+ end.to fail_with(message)
236
+ end
237
+ end
238
+
239
+ describe '#with_scope' do
240
+
241
+ subject do
242
+ User.new
243
+ end
244
+
245
+ it 'accepts when scope is defined as a boolean' do
246
+ expect(subject).to enumerize(:sex).in(:male, :female).with_scope(true)
247
+ end
248
+
249
+ it 'accepts when scope is defined as a hash' do
250
+ expect(subject).to enumerize(:role).in(:user, :admin).with_scope(scope: :having_role)
251
+ end
252
+
253
+ it 'rejects when scope is not defined' do
254
+ message = 'Expected User to define enumerize :account_type in: "basic", "premium" scope: true'
255
+ expect do
256
+ expect(subject).to enumerize(:account_type).in(:basic, :premium).with_scope(true)
257
+ end.to fail_with(message)
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+ require 'enumerize'
5
+ require 'rspec/matchers/fail_matchers'
6
+
7
+ RSpec.configure do |config|
8
+ config.disable_monkey_patching!
9
+ config.order = :random
10
+ Kernel.srand config.seed
11
+ config.filter_run focus: true
12
+ config.run_all_when_everything_filtered = true
13
+
14
+ config.expect_with :rspec do |expectations|
15
+ expectations.syntax = :expect
16
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
17
+ end
18
+
19
+ config.mock_with :rspec do |mocks|
20
+ mocks.syntax = :expect
21
+ mocks.verify_partial_doubles = true
22
+ end
23
+
24
+ if config.files_to_run.one?
25
+ config.default_formatter = 'doc'
26
+ end
27
+
28
+ config.warnings = true
29
+ config.include RSpec::Matchers::FailMatchers
30
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ if defined?(::ActiveModel::Attributes)
6
+
7
+ describe Enumerize do
8
+ class ActiveModelUser
9
+ include ActiveModel::Model
10
+ include ActiveModel::Attributes
11
+ extend Enumerize
12
+
13
+ attribute :name, :string
14
+ enumerize :sex, :in => %w[male female]
15
+ enumerize :role, :in => %w[admin user], :default => 'user'
16
+ enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true
17
+ end
18
+
19
+ class InterestsRequiredActiveModelUser < ActiveModelUser
20
+ validates :interests, presence: true
21
+ end
22
+
23
+ let(:model) { ActiveModelUser }
24
+
25
+ it 'initialize value' do
26
+ user = model.new(:name => 'active_model_user', :sex => :male, :role => :user, :interests => [:music, :programming])
27
+ user.sex.must_equal 'male'
28
+ user.sex_text.must_equal 'Male'
29
+ user.role.must_equal 'user'
30
+ user.role_text.must_equal 'User'
31
+ user.interests.must_equal %w(music programming)
32
+ end
33
+
34
+ it 'sets nil if invalid value is passed' do
35
+ user = model.new
36
+ user.sex = :invalid
37
+ user.sex.must_be_nil
38
+ end
39
+
40
+ it 'stores value' do
41
+ user = model.new
42
+ user.sex = :female
43
+ user.sex.must_equal 'female'
44
+ end
45
+
46
+ it 'has default value' do
47
+ model.new.role.must_equal 'user'
48
+ end
49
+
50
+ it 'validates inclusion' do
51
+ user = model.new
52
+ user.role = 'wrong'
53
+ user.wont_be :valid?
54
+ end
55
+
56
+ it 'supports multiple attributes' do
57
+ user = ActiveModelUser.new
58
+ user.interests.must_be_instance_of Enumerize::Set
59
+ user.interests.must_be_empty
60
+ user.interests << :music
61
+ user.interests.must_equal %w(music)
62
+ user.interests << :sports
63
+ user.interests.must_equal %w(music sports)
64
+
65
+ user.interests = []
66
+ interests = user.interests
67
+ interests << :music
68
+ interests.must_equal %w(music)
69
+ interests << :dancing
70
+ interests.must_equal %w(music dancing)
71
+ end
72
+
73
+ it 'returns invalid multiple value for validation' do
74
+ user = ActiveModelUser.new
75
+ user.interests << :music
76
+ user.interests << :invalid
77
+ values = user.read_attribute_for_validation(:interests)
78
+ values.must_equal %w(music invalid)
79
+ end
80
+
81
+ it 'validates multiple attributes' do
82
+ user = ActiveModelUser.new
83
+ user.interests << :invalid
84
+ user.wont_be :valid?
85
+
86
+ user.interests = Object.new
87
+ user.wont_be :valid?
88
+
89
+ user.interests = ['music', '']
90
+ user.must_be :valid?
91
+ end
92
+
93
+ it 'validates presence with multiple attributes' do
94
+ user = InterestsRequiredActiveModelUser.new
95
+ user.interests = []
96
+ user.valid?
97
+
98
+ user.errors[:interests].wont_be :empty?
99
+
100
+ user.interests = ['']
101
+ user.valid?
102
+
103
+ user.errors[:interests].wont_be :empty?
104
+
105
+ user.interests = [:dancing, :programming]
106
+ user.valid?
107
+
108
+ user.errors[:interests].must_be_empty
109
+ end
110
+ end
111
+
112
+ else
113
+ # Skip
114
+ end