enumerize 0.8.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -12
  5. data/CHANGELOG.md +112 -0
  6. data/Gemfile +5 -22
  7. data/Gemfile.global +19 -0
  8. data/Gemfile.mongo_mapper +6 -0
  9. data/Gemfile.rails42 +6 -0
  10. data/README.md +185 -9
  11. data/Rakefile +2 -4
  12. data/enumerize.gemspec +1 -0
  13. data/lib/enumerize/activerecord.rb +17 -28
  14. data/lib/enumerize/attribute.rb +41 -9
  15. data/lib/enumerize/base.rb +28 -17
  16. data/lib/enumerize/hooks/formtastic.rb +3 -8
  17. data/lib/enumerize/hooks/sequel_dataset.rb +15 -0
  18. data/lib/enumerize/hooks/simple_form.rb +5 -11
  19. data/lib/enumerize/hooks/uniqueness.rb +3 -8
  20. data/lib/enumerize/integrations/rspec/matcher.rb +107 -26
  21. data/lib/enumerize/mongoid.rb +13 -0
  22. data/lib/enumerize/predicatable.rb +7 -16
  23. data/lib/enumerize/predicates.rb +3 -1
  24. data/lib/enumerize/scope/activerecord.rb +37 -0
  25. data/lib/enumerize/scope/mongoid.rb +35 -0
  26. data/lib/enumerize/scope/sequel.rb +40 -0
  27. data/lib/enumerize/sequel.rb +57 -0
  28. data/lib/enumerize/set.rb +18 -8
  29. data/lib/enumerize/value.rb +10 -9
  30. data/lib/enumerize/version.rb +1 -1
  31. data/lib/enumerize.rb +23 -1
  32. data/spec/enumerize/integrations/rspec/matcher_spec.rb +258 -0
  33. data/spec/spec_helper.rb +28 -0
  34. data/test/activerecord_test.rb +143 -7
  35. data/test/attribute_test.rb +22 -0
  36. data/test/base_test.rb +2 -2
  37. data/test/formtastic_test.rb +3 -12
  38. data/test/mongo_mapper_test.rb +6 -0
  39. data/test/mongoid_test.rb +62 -6
  40. data/test/multiple_test.rb +21 -0
  41. data/test/predicates_test.rb +6 -0
  42. data/test/sequel_test.rb +291 -0
  43. data/test/set_test.rb +14 -0
  44. data/test/simple_form_test.rb +0 -1
  45. data/test/support/view_test_helper.rb +4 -0
  46. data/test/test_helper.rb +23 -2
  47. data/test/value_test.rb +51 -21
  48. metadata +39 -9
  49. data/Gemfile.rails4 +0 -23
  50. data/lib/enumerize/form_helper.rb +0 -23
  51. data/test/rspec_matcher_test.rb +0 -76
  52. data/test/rspec_spec.rb +0 -13
@@ -15,13 +15,13 @@ ActiveRecord::Base.connection.instance_eval do
15
15
  t.string :lambda_role
16
16
  t.string :name
17
17
  t.string :interests
18
- t.string :status
18
+ t.integer :status
19
19
  t.string :account_type, :default => :basic
20
20
  end
21
21
 
22
22
  create_table :documents do |t|
23
23
  t.string :visibility
24
- t.timestamps
24
+ t.timestamps null: true
25
25
  end
26
26
  end
27
27
 
@@ -53,10 +53,19 @@ class User < ActiveRecord::Base
53
53
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: true
54
54
 
55
55
  enumerize :account_type, :in => [:basic, :premium]
56
+
57
+ # There is no column for relationship enumeration for testing purposes: model
58
+ # should not be broken even if the associated column does not exist yet.
59
+ enumerize :relationship, :in => [:single, :married]
56
60
  end
57
61
 
58
62
  class UniqStatusUser < User
59
63
  validates :status, uniqueness: true
64
+ validates :sex, presence: true
65
+ end
66
+
67
+ class InterestsRequiredUser < User
68
+ validates :interests, presence: true
60
69
  end
61
70
 
62
71
  describe Enumerize::ActiveRecordSupport do
@@ -92,7 +101,8 @@ describe Enumerize::ActiveRecordSupport do
92
101
  it 'does not set default value for not selected attributes' do
93
102
  User.delete_all
94
103
  User.create!(:sex => :male)
95
- User.select(:id).collect(&:id)
104
+
105
+ assert_equal ['id'], User.select(:id).first.attributes.keys
96
106
  end
97
107
 
98
108
  it 'has default value with lambda' do
@@ -128,9 +138,18 @@ describe Enumerize::ActiveRecordSupport do
128
138
  user.errors[:role].must_include 'is not included in the list'
129
139
  end
130
140
 
131
- it 'validates inclusion when using write_attribute' do
141
+ it 'validates inclusion when using write_attribute with string attribute' do
142
+ user = User.new
143
+ user.send(:write_attribute, 'role', 'wrong')
144
+ user.read_attribute_for_validation(:role).must_equal 'wrong'
145
+ user.wont_be :valid?
146
+ user.errors[:role].must_include 'is not included in the list'
147
+ end
148
+
149
+ it 'validates inclusion when using write_attribute with symbol attribute' do
132
150
  user = User.new
133
151
  user.send(:write_attribute, :role, 'wrong')
152
+ user.read_attribute_for_validation(:role).must_equal 'wrong'
134
153
  user.wont_be :valid?
135
154
  user.errors[:role].must_include 'is not included in the list'
136
155
  end
@@ -143,7 +162,7 @@ describe Enumerize::ActiveRecordSupport do
143
162
 
144
163
  it "uses persisted value for validation if it hasn't been set" do
145
164
  user = User.create! :sex => :male
146
- User.find(user).read_attribute_for_validation(:sex).must_equal 'male'
165
+ User.find(user.id).read_attribute_for_validation(:sex).must_equal 'male'
147
166
  end
148
167
 
149
168
  it 'is valid with empty string assigned' do
@@ -179,6 +198,13 @@ describe Enumerize::ActiveRecordSupport do
179
198
  interests.must_equal %w(music dancing)
180
199
  end
181
200
 
201
+ it 'stores multiple value passed passed to new' do
202
+ user = User.new(interests: [:music, :dancing])
203
+ user.save!
204
+ user.interests.must_equal %w(music dancing)
205
+ User.find(user.id).interests.must_equal %w(music dancing)
206
+ end
207
+
182
208
  it 'returns invalid multiple value for validation' do
183
209
  user = User.new
184
210
  user.interests << :music
@@ -199,6 +225,22 @@ describe Enumerize::ActiveRecordSupport do
199
225
  user.must_be :valid?
200
226
  end
201
227
 
228
+ it 'stores custom values for multiple attributes' do
229
+ User.delete_all
230
+
231
+ klass = Class.new(User)
232
+ klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true
233
+
234
+ user = klass.new
235
+ user.interests << :music
236
+ user.read_attribute(:interests).must_equal [0]
237
+ user.interests.must_equal %w(music)
238
+ user.save
239
+
240
+ user = klass.find(user.id)
241
+ user.interests.must_equal %w(music)
242
+ end
243
+
202
244
  it 'adds scope' do
203
245
  User.delete_all
204
246
 
@@ -215,6 +257,12 @@ describe Enumerize::ActiveRecordSupport do
215
257
  User.having_role(:admin).must_equal [user_1]
216
258
  end
217
259
 
260
+ it 'ignores not enumerized values that passed to the scope method' do
261
+ User.delete_all
262
+
263
+ User.with_status(:foo).must_equal []
264
+ end
265
+
218
266
  it 'allows either key or value as valid' do
219
267
  user_1 = User.new(status: :active)
220
268
  user_2 = User.new(status: 1)
@@ -258,6 +306,36 @@ describe Enumerize::ActiveRecordSupport do
258
306
  user.errors[:status].wont_be :empty?
259
307
  end
260
308
 
309
+ it 'validates presence with multiple attributes' do
310
+ user = InterestsRequiredUser.new
311
+ user.interests = []
312
+ user.valid?
313
+
314
+ user.errors[:interests].wont_be :empty?
315
+
316
+ user.interests = ['']
317
+ user.valid?
318
+
319
+ user.errors[:interests].wont_be :empty?
320
+
321
+ user.interests = [:dancing, :programming]
322
+ user.valid?
323
+
324
+ user.errors[:interests].must_be_empty
325
+ end
326
+
327
+ it 'is valid after #becomes' do
328
+ User.delete_all
329
+ user = User.new
330
+ user.sex = :male
331
+ user.save!
332
+
333
+ uniq_user = User.find(user.id).becomes(UniqStatusUser)
334
+ uniq_user.valid?
335
+
336
+ uniq_user.errors.must_be_empty
337
+ end
338
+
261
339
  it 'supports multiple attributes in #becomes' do
262
340
  User.delete_all
263
341
 
@@ -291,7 +369,65 @@ describe Enumerize::ActiveRecordSupport do
291
369
  user = User.create(:status => :active)
292
370
  user.status = :blocked
293
371
 
294
- expected = ActiveSupport::HashWithIndifferentAccess.new(status: [1, 2]).to_yaml
295
- assert_equal expected, user.changes.to_yaml
372
+ assert_equal [1, 2], YAML.load(user.changes.to_yaml)[:status]
373
+ end
374
+
375
+ it 'allows using update_all' do
376
+ User.delete_all
377
+
378
+ user = User.create(status: :active, account_type: :premium)
379
+
380
+ User.update_all(status: :blocked)
381
+ user.reload
382
+ user.status.must_equal 'blocked'
383
+
384
+ User.update_all(status: :active, account_type: :basic)
385
+ user.reload
386
+ user.status.must_equal 'active'
387
+ user.account_type.must_equal 'basic'
388
+ end
389
+
390
+ it 'allows using update_all for multiple enumerize' do
391
+ User.delete_all
392
+
393
+ klass = Class.new(User)
394
+ klass.enumerize :interests, in: { music: 0, sports: 1, dancing: 2, programming: 3}, multiple: true
395
+
396
+ user = klass.create(status: :active)
397
+ klass.update_all(status: :blocked, interests: [:music, :dancing])
398
+
399
+ user = klass.find(user.id)
400
+ user.status.must_equal 'blocked'
401
+ user.interests.must_equal %w(music dancing)
402
+ end
403
+
404
+ it 'allows using update_all with values' do
405
+ User.delete_all
406
+
407
+ user = User.create(status: :active)
408
+
409
+ User.update_all(status: 2)
410
+ user.reload
411
+ user.status.must_equal 'blocked'
412
+ end
413
+
414
+ it 'preserves string usage of update_all' do
415
+ User.delete_all
416
+
417
+ user = User.create(name: "Fred")
418
+
419
+ User.update_all("name = 'Frederick'")
420
+ user.reload
421
+ user.name.must_equal 'Frederick'
422
+ end
423
+
424
+ it 'preserves interpolated array usage of update_all' do
425
+ User.delete_all
426
+
427
+ user = User.create(name: "Fred")
428
+
429
+ User.update_all(["name = :name", {name: 'Frederick'}])
430
+ user.reload
431
+ user.name.must_equal 'Frederick'
296
432
  end
297
433
  end
@@ -19,6 +19,12 @@ describe Enumerize::Attribute do
19
19
  attr.name.must_equal :foo
20
20
  end
21
21
 
22
+ it 'uses custom value class' do
23
+ value_class = Class.new(Enumerize::Value)
24
+ build_attr nil, 'foo', :in => %w[a b], :value_class => value_class
25
+ attr.values.first.must_be_instance_of value_class
26
+ end
27
+
22
28
  describe 'i18n scopes' do
23
29
  it 'returns scopes from options' do
24
30
  build_attr nil, 'foo', :in => %w[a b], :i18n_scope => %w[bar buzz]
@@ -79,6 +85,18 @@ describe Enumerize::Attribute do
79
85
  end
80
86
  end
81
87
 
88
+ it 'sets up shortcut methods for each value' do
89
+ build_attr nil, :foo, :in => {:a => 1, :b => 2}
90
+
91
+ attr.must_respond_to :a
92
+ attr.must_respond_to :b
93
+
94
+ attr.a.value.must_equal 1
95
+ attr.b.value.must_equal 2
96
+ attr.a.text.must_equal 'A'
97
+ attr.b.text.must_equal 'B'
98
+ end
99
+
82
100
  describe 'values hash with zero' do
83
101
  before do
84
102
  build_attr nil, :foo, :in => {:a => 1, :b => 2, :c => 0}
@@ -93,6 +111,10 @@ describe Enumerize::Attribute do
93
111
  attr.find_value(2).must_equal 'b'
94
112
  attr.find_value(0).must_equal 'c'
95
113
  end
114
+
115
+ it 'finds all values by hash values' do
116
+ attr.find_values(1, 2, 0).must_equal ['a', 'b', 'c']
117
+ end
96
118
  end
97
119
 
98
120
  describe 'boolean values hash' do
data/test/base_test.rb CHANGED
@@ -41,7 +41,7 @@ describe Enumerize::Base do
41
41
  end
42
42
  end
43
43
 
44
- it 'scopes translation by i18 key' do
44
+ it 'scopes translation by i18n key' do
45
45
  def klass.model_name
46
46
  name = "ExampleClass"
47
47
  def name.i18n_key
@@ -171,7 +171,7 @@ describe Enumerize::Base do
171
171
 
172
172
  object = klass.new
173
173
  object.foo.must_be_nil
174
- object.attributes.must_equal({:foo => nil})
174
+ object.attributes.must_equal({})
175
175
 
176
176
  object.foo = 'test'
177
177
  object.foo.must_equal 'test'
@@ -1,16 +1,7 @@
1
1
  require 'test_helper'
2
- require 'rails'
3
-
4
- module Formtastic
5
- module Helpers
6
- module InputHelper
7
- remove_method :input_class
8
- def input_class(as)
9
- input_class_with_const_defined(as)
10
- end
11
- end
12
- end
13
- end
2
+
3
+ Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder
4
+ Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
14
5
 
15
6
  class FormtasticSpec < MiniTest::Spec
16
7
  include ViewTestHelper
@@ -1,5 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
+ begin
4
+
3
5
  silence_warnings do
4
6
  require 'mongo_mapper'
5
7
  end
@@ -66,3 +68,7 @@ describe Enumerize do
66
68
  user.sex.must_equal 'female'
67
69
  end
68
70
  end
71
+
72
+ rescue LoadError
73
+ # Skip
74
+ end
data/test/mongoid_test.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  require 'test_helper'
2
2
 
3
+ begin
4
+
3
5
  silence_warnings do
4
6
  require 'mongoid'
5
7
  end
6
8
 
7
9
  Mongoid.configure do |config|
8
- config.sessions = { :default => { :database => 'enumerize-test-suite', hosts: ['127.0.0.1:27017'] } }
9
- config.use_utc = true
10
- config.include_root_in_json = true
10
+ config.connect_to('enumerize-test-suite')
11
+ config.options = { use_utc: true, include_root_in_json: true }
11
12
  end
12
13
 
13
14
  describe Enumerize do
@@ -17,9 +18,10 @@ describe Enumerize do
17
18
 
18
19
  field :sex
19
20
  field :role
20
- enumerize :sex, :in => %w[male female]
21
- enumerize :role, :in => %w[admin user], :default => 'user'
22
- enumerize :mult, :in => %w[one two three four], :multiple => true
21
+ enumerize :sex, :in => %w[male female], scope: true
22
+ enumerize :status, :in => %w[notice warning error], scope: true
23
+ enumerize :role, :in => %w[admin user], :default => 'user', scope: :having_role
24
+ enumerize :mult, :in => %w[one two three four], :multiple => true
23
25
  end
24
26
 
25
27
  before { $VERBOSE = nil }
@@ -55,6 +57,21 @@ describe Enumerize do
55
57
  model.new.role.must_equal 'user'
56
58
  end
57
59
 
60
+ it 'uses after_initialize callback to set default value' do
61
+ model.delete_all
62
+ model.create!(sex: 'male', role: nil)
63
+
64
+ user = model.where(sex: 'male').first
65
+ user.role.must_equal 'user'
66
+ end
67
+
68
+ it 'does not set default value for not selected attributes' do
69
+ model.delete_all
70
+ model.create!(sex: :male)
71
+
72
+ assert_equal ['_id'], model.only(:id).first.attributes.keys
73
+ end
74
+
58
75
  it 'validates inclusion' do
59
76
  user = model.new
60
77
  user.role = 'wrong'
@@ -76,4 +93,43 @@ describe Enumerize do
76
93
  user = model.first
77
94
  user.mult.to_a.must_equal ['one', 'two']
78
95
  end
96
+
97
+ it 'adds scope' do
98
+ model.delete_all
99
+
100
+ user_1 = model.create!(sex: :male, role: :admin)
101
+ user_2 = model.create!(sex: :female, role: :user)
102
+
103
+ model.with_sex(:male).to_a.must_equal [user_1]
104
+ model.with_sex(:female).to_a.must_equal [user_2]
105
+ model.with_sex(:male, :female).to_set.must_equal [user_1, user_2].to_set
106
+
107
+ model.without_sex(:male).to_a.must_equal [user_2]
108
+ model.without_sex(:female).to_a.must_equal [user_1]
109
+ model.without_sex(:male, :female).to_a.must_equal []
110
+
111
+ model.having_role(:admin).to_a.must_equal [user_1]
112
+ model.having_role(:user).to_a.must_equal [user_2]
113
+ end
114
+
115
+ it 'chains scopes' do
116
+ model.delete_all
117
+
118
+ user_1 = model.create!(status: :notice)
119
+ user_2 = model.create!(status: :warning)
120
+ user_3 = model.create!(status: :error)
121
+
122
+ model.with_status(:notice, :warning).with_status(:notice, :error).to_a.must_equal [user_1]
123
+ model.with_status(:notice, :warning).union.with_status(:notice, :error).to_a.must_equal [user_1, user_2, user_3]
124
+ end
125
+
126
+ it 'ignores not enumerized values that passed to the scope method' do
127
+ model.delete_all
128
+
129
+ model.with_sex(:foo).must_equal []
130
+ end
131
+ end
132
+
133
+ rescue LoadError
134
+ # Skip
79
135
  end
@@ -24,6 +24,21 @@ describe Enumerize::Base do
24
24
  object.foos.must_equal %w(a c)
25
25
  end
26
26
 
27
+ it 'sets default value as single value' do
28
+ klass.enumerize :foos, in: %w(a b c), default: 'b', multiple: true
29
+ object.foos.must_equal %w(b)
30
+ end
31
+
32
+ it 'sets default value as array of one element' do
33
+ klass.enumerize :foos, in: %w(a b c), default: %w(b), multiple: true
34
+ object.foos.must_equal %w(b)
35
+ end
36
+
37
+ it 'sets default value as array of several elements' do
38
+ klass.enumerize :foos, in: %w(a b c), default: %w(b c), multiple: true
39
+ object.foos.must_equal %w(b c)
40
+ end
41
+
27
42
  it "doesn't define _text method" do
28
43
  klass.enumerize :foos, in: %w(a b c), multiple: true
29
44
  object.wont_respond_to :foos_text
@@ -33,4 +48,10 @@ describe Enumerize::Base do
33
48
  klass.enumerize :foos, in: %w(a b c), multiple: true
34
49
  object.wont_respond_to :foos_value
35
50
  end
51
+
52
+ it "cannot define multiple with scope" do
53
+ assert_raises ArgumentError do
54
+ klass.enumerize :foos, in: %w(a b c), multiple: true, scope: true
55
+ end
56
+ end
36
57
  end
@@ -15,6 +15,12 @@ describe Enumerize::Predicates do
15
15
  object.must_respond_to :b?
16
16
  end
17
17
 
18
+ it 'creates predicate methods when enumerized values have dash in it' do
19
+ klass.enumerize(:foo, in: %w(foo-bar bar-foo), predicates: true)
20
+ object.must_respond_to :foo_bar?
21
+ object.must_respond_to :bar_foo?
22
+ end
23
+
18
24
  it 'creates predicate methods on multiple attribute' do
19
25
  klass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true)
20
26
  object.must_respond_to :a?