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
data/test/mongoid_test.rb CHANGED
@@ -1,24 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
5
+ begin
6
+
3
7
  silence_warnings do
4
8
  require 'mongoid'
5
9
  end
6
10
 
7
11
  Mongoid.configure do |config|
8
- config.master = Mongo::Connection.new('127.0.0.1', 27017).db('enumerize-test-suite')
9
- config.use_utc = true
10
- config.include_root_in_json = true
12
+ config.connect_to('enumerize-test-suite')
13
+ config.options = { use_utc: true, include_root_in_json: true }
11
14
  end
12
15
 
13
16
  describe Enumerize do
14
17
  class MongoidUser
15
18
  include Mongoid::Document
16
- include Enumerize
19
+ extend Enumerize
17
20
 
18
21
  field :sex
19
22
  field :role
20
- enumerize :sex, :in => %w[male female]
21
- enumerize :role, :in => %w[admine user], :default => 'user'
23
+ field :foo
24
+ field :skill
25
+
26
+ enumerize :sex, :in => %w[male female], scope: true
27
+ enumerize :status, :in => %w[notice warning error], scope: true
28
+ enumerize :role, :in => %w[admin user], :default => 'user', scope: :having_role
29
+ enumerize :mult, :in => %w[one two three four], :multiple => true
30
+ enumerize :foo, :in => %w[bar baz], :skip_validations => true
31
+ enumerize :skill, :in => { noob: 0, casual: 1, pro: 2 }, scope: :shallow
32
+ enumerize :account_type, :in => %w[basic premium], scope: :shallow
22
33
  end
23
34
 
24
35
  before { $VERBOSE = nil }
@@ -29,7 +40,7 @@ describe Enumerize do
29
40
  it 'sets nil if invalid value is passed' do
30
41
  user = model.new
31
42
  user.sex = :invalid
32
- user.sex.must_equal nil
43
+ user.sex.must_be_nil
33
44
  end
34
45
 
35
46
  it 'saves value' do
@@ -54,12 +65,41 @@ describe Enumerize do
54
65
  model.new.role.must_equal 'user'
55
66
  end
56
67
 
68
+ it 'uses after_initialize callback to set default value' do
69
+ model.delete_all
70
+ model.create!(sex: 'male', role: nil)
71
+
72
+ user = model.where(sex: 'male').first
73
+ user.role.must_equal 'user'
74
+ end
75
+
76
+ it 'does not set default value for not selected attributes' do
77
+ model.delete_all
78
+ model.create!(sex: :male)
79
+
80
+ assert_equal ['_id'], model.only(:id).first.attributes.keys
81
+ end
82
+
57
83
  it 'validates inclusion' do
58
84
  user = model.new
59
85
  user.role = 'wrong'
60
86
  user.wont_be :valid?
61
87
  end
62
88
 
89
+ it 'does not validate inclusion when :skip_validations option passed' do
90
+ user = model.new
91
+ user.foo = 'wrong'
92
+ user.must_be :valid?
93
+ end
94
+
95
+ it 'sets value to enumerized field from db when record is reloaded' do
96
+ user = model.create!(mult: [:one])
97
+ model.find(user.id).update(mult: %i[two three])
98
+ user.mult.must_equal %w[one]
99
+ user.reload
100
+ user.mult.must_equal %w[two three]
101
+ end
102
+
63
103
  it 'assigns value on loaded record' do
64
104
  model.delete_all
65
105
  model.create!(:sex => :male)
@@ -67,4 +107,55 @@ describe Enumerize do
67
107
  user.sex = :female
68
108
  user.sex.must_equal 'female'
69
109
  end
110
+
111
+ it 'loads multiple properly' do
112
+ model.delete_all
113
+
114
+ model.create!(:mult => ['one', 'two'])
115
+ user = model.first
116
+ user.mult.to_a.must_equal ['one', 'two']
117
+ end
118
+
119
+ it 'adds scope' do
120
+ model.delete_all
121
+
122
+ user_1 = model.create!(sex: :male, role: :admin)
123
+ user_2 = model.create!(sex: :female, role: :user)
124
+ user_3 = model.create!(skill: :pro, account_type: :premium)
125
+
126
+ model.with_sex(:male).to_a.must_equal [user_1]
127
+ model.with_sex(:female).to_a.must_equal [user_2]
128
+ model.with_sex(:male, :female).to_set.must_equal [user_1, user_2].to_set
129
+
130
+ model.without_sex(:male).to_set.must_equal [user_2, user_3].to_set
131
+ model.without_sex(:female).to_set.must_equal [user_1, user_3].to_set
132
+ model.without_sex(:male, :female).to_a.must_equal [user_3]
133
+
134
+ model.having_role(:admin).to_a.must_equal [user_1]
135
+ model.having_role(:user).to_a.must_equal [user_2, user_3]
136
+
137
+ model.pro.to_a.must_equal [user_3]
138
+ model.premium.to_a.must_equal [user_3]
139
+ end
140
+
141
+ it 'chains scopes' do
142
+ model.delete_all
143
+
144
+ user_1 = model.create!(status: :notice)
145
+ user_2 = model.create!(status: :warning)
146
+ user_3 = model.create!(status: :error)
147
+
148
+ model.with_status(:notice, :warning).with_status(:notice, :error).to_a.must_equal [user_1]
149
+ model.with_status(:notice, :warning).union.with_status(:notice, :error).to_a.must_equal [user_1, user_2, user_3]
150
+ end
151
+
152
+ it 'ignores not enumerized values that passed to the scope method' do
153
+ model.delete_all
154
+
155
+ model.with_sex(:foo).must_equal []
156
+ end
157
+ end
158
+
159
+ rescue LoadError
160
+ # Skip
70
161
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ describe Enumerize::Base do
6
+ let(:kklass) do
7
+ Class.new do
8
+ extend Enumerize
9
+ end
10
+ end
11
+
12
+ let(:subklass) do
13
+ Class.new(kklass)
14
+ end
15
+
16
+ let(:object) { kklass.new }
17
+
18
+ it 'returns [] when not set' do
19
+ kklass.enumerize :foos, in: %w(a b), multiple: true
20
+ object.foos.must_equal []
21
+ end
22
+
23
+ it 'returns setted array' do
24
+ kklass.enumerize :foos, in: %w(a b c), multiple: true
25
+ object.foos = %w(a c)
26
+ object.foos.must_equal %w(a c)
27
+ end
28
+
29
+ it 'sets default value as single value' do
30
+ kklass.enumerize :foos, in: %w(a b c), default: 'b', multiple: true
31
+ object.foos.must_equal %w(b)
32
+ end
33
+
34
+ it 'sets default value as array of one element' do
35
+ kklass.enumerize :foos, in: %w(a b c), default: %w(b), multiple: true
36
+ object.foos.must_equal %w(b)
37
+ end
38
+
39
+ it 'sets default value as array of several elements' do
40
+ kklass.enumerize :foos, in: %w(a b c), default: %w(b c), multiple: true
41
+ object.foos.must_equal %w(b c)
42
+ end
43
+
44
+ it "doesn't define _text method" do
45
+ kklass.enumerize :foos, in: %w(a b c), multiple: true
46
+ object.wont_respond_to :foos_text
47
+ end
48
+
49
+ it "doesn't define _value method" do
50
+ kklass.enumerize :foos, in: %w(a b c), multiple: true
51
+ object.wont_respond_to :foos_value
52
+ end
53
+
54
+ it "cannot define multiple with scope" do
55
+ assert_raises ArgumentError do
56
+ kklass.enumerize :foos, in: %w(a b c), multiple: true, scope: true
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ describe Enumerize::Predicates do
6
+ let(:kklass) do
7
+ Class.new do
8
+ extend Enumerize
9
+ end
10
+ end
11
+
12
+ let(:object) { kklass.new }
13
+
14
+ it 'creates predicate methods' do
15
+ kklass.enumerize(:foo, in: %w(a b), predicates: true)
16
+ object.must_respond_to :a?
17
+ object.must_respond_to :b?
18
+ end
19
+
20
+ it 'creates predicate methods when enumerized values have dash in it' do
21
+ kklass.enumerize(:foo, in: %w(foo-bar bar-foo), predicates: true)
22
+ object.must_respond_to :foo_bar?
23
+ object.must_respond_to :bar_foo?
24
+ end
25
+
26
+ it 'creates predicate methods on multiple attribute' do
27
+ kklass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true)
28
+ object.must_respond_to :a?
29
+ object.must_respond_to :b?
30
+ end
31
+
32
+ it 'checks values' do
33
+ kklass.enumerize(:foo, in: %w(a b), predicates: true)
34
+ object.foo = 'a'
35
+ object.a?.must_equal true
36
+ object.b?.must_equal false
37
+ end
38
+
39
+ it 'checks values on multiple attribute' do
40
+ kklass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true)
41
+ object.foo << :a
42
+ object.a?.must_equal true
43
+ object.b?.must_equal false
44
+ end
45
+
46
+ it 'prefixes methods' do
47
+ kklass.enumerize(:foo, in: %w(a b), predicates: { prefix: 'bar' })
48
+ object.wont_respond_to :a?
49
+ object.wont_respond_to :b?
50
+ object.must_respond_to :bar_a?
51
+ object.must_respond_to :bar_b?
52
+ end
53
+
54
+ it 'accepts only option' do
55
+ kklass.enumerize(:foo, in: %w(a b), predicates: { only: :a })
56
+ object.must_respond_to :a?
57
+ object.wont_respond_to :b?
58
+ end
59
+
60
+ it 'accepts except option' do
61
+ kklass.enumerize(:foo, in: %w(a b), predicates: { except: :a })
62
+ object.wont_respond_to :a?
63
+ object.must_respond_to :b?
64
+ end
65
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class RailsAdminSpec < MiniTest::Spec
6
+ let(:kklass) do
7
+ Class.new do
8
+ extend Enumerize
9
+ end
10
+ end
11
+
12
+ let(:object) { kklass.new }
13
+
14
+ it 'defines enum method' do
15
+ store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do
16
+ kklass.enumerize(:foo, in: [:a, :b])
17
+ object.foo_enum.must_equal [['a text', 'a'], ['b text', 'b']]
18
+ end
19
+ end
20
+
21
+ it 'defines enum properly for custom values enumerations' do
22
+ store_translations(:en, :enumerize => {:foo => {:a => 'a text', :b => 'b text'}}) do
23
+ kklass.enumerize(:foo, in: {:a => 1, :b => 2})
24
+ object.foo_enum.must_equal [['a text', 'a'], ['b text', 'b']]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,341 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'sequel'
5
+ require 'logger'
6
+ require 'jdbc/sqlite3' if RUBY_PLATFORM == 'java'
7
+
8
+ module SequelTest
9
+ silence_warnings do
10
+ DB = if RUBY_PLATFORM == 'java'
11
+ Sequel.connect('jdbc:sqlite::memory:')
12
+ else
13
+ Sequel.sqlite
14
+ end
15
+ DB.loggers << Logger.new(nil)
16
+ end
17
+
18
+ DB.create_table :users do
19
+ primary_key :id
20
+ String :sex
21
+ String :role
22
+ String :lambda_role
23
+ String :name
24
+ String :interests
25
+ String :status
26
+ Integer :skill
27
+ String :account_type, default: "basic"
28
+ String :foo
29
+ end
30
+
31
+ DB.create_table :documents do
32
+ primary_key :id
33
+ String :visibility
34
+ Time :created_at
35
+ Time :updated_at
36
+ end
37
+
38
+ class Document < Sequel::Model
39
+ plugin :enumerize
40
+ enumerize :visibility, :in => [:public, :private, :protected], :scope => true, :default => :public
41
+ end
42
+
43
+ module RoleEnum
44
+ extend Enumerize
45
+ enumerize :role, :in => [:user, :admin], :default => :user, scope: :having_role
46
+ enumerize :lambda_role, :in => [:user, :admin], :default => lambda { :admin }
47
+ end
48
+
49
+ class User < Sequel::Model
50
+ plugin :serialization, :json, :interests
51
+ plugin :dirty
52
+ plugin :defaults_setter
53
+ plugin :validation_helpers
54
+ plugin :enumerize
55
+ include RoleEnum
56
+
57
+ enumerize :sex, :in => [:male, :female], scope: :shallow
58
+
59
+ enumerize :interests, :in => [:music, :sports, :dancing, :programming], :multiple => true
60
+
61
+ enumerize :status, :in => { active: 1, blocked: 2 }, scope: true
62
+
63
+ enumerize :skill, :in => { noob: 0, casual: 1, pro: 2 }, scope: :shallow
64
+
65
+ enumerize :account_type, :in => [:basic, :premium]
66
+ end
67
+
68
+ class UniqStatusUser < User
69
+ def validate
70
+ super
71
+ validates_unique :status
72
+ validates_presence :sex
73
+ end
74
+ end
75
+
76
+ class SkipValidationsUser < Sequel::Model(:users)
77
+ include SkipValidationsEnum
78
+ end
79
+
80
+ class DoNotSkipValidationsUser < Sequel::Model(:users)
81
+ include DoNotSkipValidationsEnum
82
+ end
83
+
84
+ class SkipValidationsLambdaUser < Sequel::Model(:users)
85
+ include SkipValidationsLambdaEnum
86
+ end
87
+
88
+ class SkipValidationsLambdaWithParamUser < Sequel::Model(:users)
89
+ include SkipValidationsLambdaWithParamEnum
90
+ end
91
+
92
+ describe Enumerize::SequelSupport do
93
+ it 'sets nil if invalid value is passed' do
94
+ user = User.new
95
+ user.sex = :invalid
96
+ user.sex.must_be_nil
97
+ end
98
+
99
+ it 'saves value' do
100
+ User.filter{ true }.delete
101
+ user = User.new
102
+ user.sex = :female
103
+ user.save
104
+ user.sex.must_equal 'female'
105
+ end
106
+
107
+ it 'loads value' do
108
+ User.filter{ true }.delete
109
+ User.create(:sex => :male)
110
+ store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do
111
+ user = User.first
112
+ user.sex.must_equal 'male'
113
+ user.sex_text.must_equal 'Male'
114
+ end
115
+ end
116
+
117
+ it 'has default value' do
118
+ User.new.role.must_equal 'user'
119
+ User.new.values[:role].must_equal 'user'
120
+ end
121
+
122
+ it 'does not set default value for not selected attributes' do
123
+ User.filter{ true }.delete
124
+ User.create(:sex => :male)
125
+
126
+ assert_equal [:id], User.select(:id).first.values.keys
127
+ end
128
+
129
+ it 'has default value with lambda' do
130
+ User.new.lambda_role.must_equal 'admin'
131
+ User.new.values[:lambda_role].must_equal 'admin'
132
+ end
133
+ it 'uses after_initialize callback to set default value' do
134
+ User.filter{ true }.delete
135
+ User.create(sex: 'male', lambda_role: nil)
136
+
137
+ user = User.where(:sex => 'male').first
138
+ user.lambda_role.must_equal 'admin'
139
+ end
140
+
141
+ it 'uses default value from db column' do
142
+ User.new.account_type.must_equal 'basic'
143
+ end
144
+
145
+ it 'validates inclusion' do
146
+ user = User.new
147
+ user.role = 'wrong'
148
+ user.wont_be :valid?
149
+ user.errors[:role].must_include 'is not included in the list'
150
+ end
151
+
152
+ it 'validates inclusion on mass assignment' do
153
+ assert_raises Sequel::ValidationFailed do
154
+ User.create(role: 'wrong')
155
+ end
156
+ end
157
+
158
+ it "uses persisted value for validation if it hasn't been set" do
159
+ user = User.create :sex => :male
160
+ User[user.id].read_attribute_for_validation(:sex).must_equal 'male'
161
+ end
162
+
163
+ it 'is valid with empty string assigned' do
164
+ user = User.new
165
+ user.role = ''
166
+ user.must_be :valid?
167
+ end
168
+
169
+ it 'stores nil when empty string assigned' do
170
+ user = User.new
171
+ user.role = ''
172
+ user.values[:role].must_be_nil
173
+ end
174
+
175
+ it 'validates inclusion when :skip_validations = false' do
176
+ user = DoNotSkipValidationsUser.new
177
+ user.foo = 'wrong'
178
+ user.wont_be :valid?
179
+ user.errors[:foo].must_include 'is not included in the list'
180
+ end
181
+
182
+ it 'does not validate inclusion when :skip_validations = true' do
183
+ user = SkipValidationsUser.new
184
+ user.foo = 'wrong'
185
+ user.must_be :valid?
186
+ end
187
+
188
+ it 'supports :skip_validations option as lambda' do
189
+ user = SkipValidationsLambdaUser.new
190
+ user.foo = 'wrong'
191
+ user.must_be :valid?
192
+ end
193
+
194
+ it 'supports :skip_validations option as lambda with a parameter' do
195
+ user = SkipValidationsLambdaWithParamUser.new
196
+ user.foo = 'wrong'
197
+ user.must_be :valid?
198
+ end
199
+
200
+ it 'supports multiple attributes' do
201
+ user = User.new
202
+ user.interests ||= []
203
+ user.interests.must_be_empty
204
+ user.interests << "music"
205
+ user.interests.must_equal %w(music)
206
+ user.save
207
+
208
+ user = User[user.id]
209
+ user.interests.must_be_instance_of Enumerize::Set
210
+ user.interests.must_equal %w(music)
211
+ user.interests << "sports"
212
+ user.interests.must_equal %w(music sports)
213
+
214
+ user.interests = []
215
+ interests = user.interests
216
+ interests << "music"
217
+ interests.must_equal %w(music)
218
+ interests << "dancing"
219
+ interests.must_equal %w(music dancing)
220
+ end
221
+
222
+ it 'returns invalid multiple value for validation' do
223
+ user = User.new
224
+ user.interests << :music
225
+ user.interests << :invalid
226
+ values = user.read_attribute_for_validation(:interests)
227
+ values.must_equal %w(music invalid)
228
+ end
229
+
230
+ it 'validates multiple attributes' do
231
+ user = User.new
232
+ user.interests << :invalid
233
+ user.wont_be :valid?
234
+
235
+ user.interests = Object.new
236
+ user.wont_be :valid?
237
+
238
+ user.interests = ['music', '']
239
+ user.must_be :valid?
240
+ end
241
+
242
+ it 'stores custom values for multiple attributes' do
243
+ User.filter{ true }.delete
244
+
245
+ klass = Class.new(User)
246
+ klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true
247
+
248
+ user = klass.new
249
+ user.interests << :music
250
+ user.interests.must_equal %w(music)
251
+ user.save
252
+
253
+ user = klass[user.id]
254
+ user.interests.must_equal %w(music)
255
+ end
256
+
257
+ it 'adds scope' do
258
+ User.filter{ true }.delete
259
+
260
+ user_1 = User.create(status: :active, role: :admin)
261
+ user_2 = User.create(status: :blocked)
262
+ user_3 = User.create(sex: :male, skill: :pro)
263
+
264
+ User.with_status(:active).to_a.must_equal [user_1]
265
+ User.with_status(:blocked).to_a.must_equal [user_2]
266
+ User.with_status(:active, :blocked).to_set.must_equal [user_1, user_2].to_set
267
+
268
+ User.without_status(:active).to_a.must_equal [user_2]
269
+ User.without_status(:active, :blocked).to_a.must_equal []
270
+
271
+ User.having_role(:admin).to_a.must_equal [user_1]
272
+ User.male.to_a.must_equal [user_3]
273
+ User.pro.to_a.must_equal [user_3]
274
+ end
275
+
276
+ it 'allows either key or value as valid' do
277
+ user_1 = User.new(status: :active)
278
+ user_2 = User.new(status: 1)
279
+ user_3 = User.new(status: '1')
280
+
281
+ user_1.status.must_equal 'active'
282
+ user_2.status.must_equal 'active'
283
+ user_3.status.must_equal 'active'
284
+
285
+ user_1.must_be :valid?
286
+ user_2.must_be :valid?
287
+ user_3.must_be :valid?
288
+ end
289
+
290
+ it 'supports defining enumerized attributes on abstract class' do
291
+ Document.filter{ true }.delete
292
+
293
+ document = Document.new
294
+ document.visibility = :protected
295
+ document.visibility.must_equal 'protected'
296
+ end
297
+
298
+ it 'supports defining enumerized scopes on abstract class' do
299
+ Document.filter{ true }.delete
300
+
301
+ document_1 = Document.create(visibility: :public)
302
+ document_2 = Document.create(visibility: :private)
303
+
304
+ Document.with_visibility(:public).to_a.must_equal [document_1]
305
+ end
306
+
307
+ it 'validates uniqueness' do
308
+ user = User.create(status: :active, sex: "male")
309
+
310
+ user = UniqStatusUser.new
311
+ user.sex = "male"
312
+ user.status = :active
313
+ user.valid?.must_equal false
314
+
315
+ user.errors[:status].wont_be :empty?
316
+ end
317
+
318
+ it "doesn't update record" do
319
+ Document.filter{ true }.delete
320
+
321
+ expected = Time.new(2010, 10, 10)
322
+
323
+ document = Document.new
324
+ document.updated_at = expected
325
+ document.save
326
+
327
+ document = Document.last
328
+ document.save
329
+
330
+ assert_equal expected, document.updated_at
331
+ end
332
+
333
+ it 'changes from dirty should be serialized as scalar values' do
334
+ user = User.create(:status => :active)
335
+ user.status = :blocked
336
+
337
+ expected = { status: [1, 2] }.to_yaml
338
+ assert_equal expected, user.column_changes.to_yaml
339
+ end
340
+ end
341
+ end