simple_enum 1.6.9 → 2.0.0.rc1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/LICENSE +1 -1
  4. data/README.md +248 -0
  5. data/Rakefile +4 -21
  6. data/lib/simple_enum/accessors/accessor.rb +55 -0
  7. data/lib/simple_enum/accessors/ignore_accessor.rb +11 -0
  8. data/lib/simple_enum/accessors/whiny_accessor.rb +12 -0
  9. data/lib/simple_enum/accessors.rb +18 -0
  10. data/lib/simple_enum/attribute.rb +77 -0
  11. data/lib/simple_enum/enum.rb +37 -0
  12. data/lib/simple_enum/hasher.rb +26 -0
  13. data/lib/simple_enum/mongoid.rb +11 -15
  14. data/lib/simple_enum/translation.rb +17 -0
  15. data/lib/simple_enum/version.rb +2 -2
  16. data/lib/simple_enum.rb +19 -276
  17. data/simple_enum.gemspec +9 -9
  18. data/spec/simple_enum/accessors_spec.rb +212 -0
  19. data/spec/simple_enum/attribute_spec.rb +208 -0
  20. data/spec/simple_enum/enum_spec.rb +96 -0
  21. data/spec/simple_enum/hasher_spec.rb +63 -0
  22. data/spec/simple_enum/mongoid_spec.rb +44 -0
  23. data/spec/simple_enum/translation_spec.rb +66 -0
  24. data/spec/spec_helper.rb +27 -0
  25. data/spec/support/active_record_support.rb +23 -0
  26. data/spec/support/i18n_support.rb +12 -0
  27. data/spec/support/model_support.rb +47 -0
  28. data/spec/support/mongoid_support.rb +21 -0
  29. metadata +50 -56
  30. data/README.rdoc +0 -293
  31. data/lib/simple_enum/enum_hash.rb +0 -64
  32. data/lib/simple_enum/validation.rb +0 -58
  33. data/locales/en.yml +0 -10
  34. data/test/array_conversions_test.rb +0 -21
  35. data/test/class_methods_test.rb +0 -114
  36. data/test/dirty_attributes_test.rb +0 -37
  37. data/test/enum_hash_test.rb +0 -73
  38. data/test/finders_test.rb +0 -45
  39. data/test/locales.yml +0 -25
  40. data/test/mongoid_test.rb +0 -66
  41. data/test/object_backed_test.rb +0 -61
  42. data/test/orm/active_record.rb +0 -114
  43. data/test/orm/common.rb +0 -23
  44. data/test/orm/mongoid.rb +0 -114
  45. data/test/poro_test.rb +0 -20
  46. data/test/prefixes_test.rb +0 -36
  47. data/test/simple_enum_test.rb +0 -314
  48. data/test/test_helper.rb +0 -40
  49. data/test/without_shortcuts_test.rb +0 -39
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleEnum::Attribute do
4
+ fake_model(:klass) { as_enum :gender, %w{male female}, with: [] }
5
+ let(:accessor) { subject.class.genders_accessor }
6
+
7
+ context '.as_enum' do
8
+ it 'returns a SimpleEnum::Enum' do
9
+ expect(klass.as_enum(:gender, %w{male female})).to be_a(SimpleEnum::Enum)
10
+ end
11
+ end
12
+
13
+ context 'generate_enum_class_accessors_for' do
14
+ context '.genders' do
15
+ subject { klass.genders }
16
+
17
+ it 'returns a SimpleEnum::Enum' do
18
+ expect(subject).to be_a(SimpleEnum::Enum)
19
+ end
20
+ end
21
+
22
+ context '.genders_accessor' do
23
+ subject { klass.genders_accessor }
24
+
25
+ it 'returns a SimpleEnum::Accessor' do
26
+ expect(subject).to be_a(SimpleEnum::Accessors::Accessor)
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'generate_enum_instance_accessors_for' do
32
+ subject { klass.new(1) }
33
+
34
+ context '#gender' do
35
+ it 'delegates to accessor' do
36
+ expect(accessor).to receive(:read).with(subject) { :female }
37
+ expect(subject.gender).to eq :female
38
+ end
39
+ end
40
+
41
+ context '#gender=' do
42
+ it 'delegates to accessor' do
43
+ expect(accessor).to receive(:write).with(subject, :male) { 0 }
44
+ subject.gender = :male
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'generate_enum_dirty_methods_for' do
50
+ subject { klass.new }
51
+
52
+ it 'does not respond to #gender_changed?' do
53
+ expect(subject).to_not respond_to(:gender_changed?)
54
+ end
55
+
56
+ it 'does not responds to #gender_was' do
57
+ expect(subject).to_not respond_to(:gender_was)
58
+ end
59
+
60
+ context 'with: :dirty' do
61
+ fake_model(:klass_with_dirty) { as_enum :gender, %w{male female}, with: [:dirty] }
62
+ subject { klass_with_dirty.new }
63
+
64
+ it 'delegates #gender_changed? to accessor' do
65
+ expect(accessor).to receive(:changed?).with(subject) { true }
66
+ expect(subject.gender_changed?).to be_true
67
+ end
68
+
69
+ it 'delegates #gender_was to accesso' do
70
+ expect(accessor).to receive(:was).with(subject) { :female }
71
+ expect(subject.gender_was).to eq :female
72
+ end
73
+ end
74
+ end
75
+
76
+ context 'generate_enum_attribute_methods_for' do
77
+ subject { klass.new }
78
+
79
+ it 'does not respond to #gender?' do
80
+ expect(subject).to_not respond_to(:gender?)
81
+ end
82
+
83
+ it 'does not respond to #male? or #female?' do
84
+ expect(subject).to_not respond_to(:male?)
85
+ expect(subject).to_not respond_to(:female?)
86
+ end
87
+
88
+ it 'does not respond to #male! or #female!' do
89
+ expect(subject).to_not respond_to(:male!)
90
+ expect(subject).to_not respond_to(:female!)
91
+ end
92
+
93
+ context 'with: :attribute' do
94
+ fake_model(:klass_with_attributes) { as_enum :gender, %w{male female}, with: [:attribute] }
95
+ subject { klass_with_attributes.new }
96
+
97
+ it 'delegates #gender? to accessor' do
98
+ expect(accessor).to receive(:selected?).with(subject, nil) { :female }
99
+ expect(subject.gender?).to be_true
100
+ end
101
+
102
+ it 'delegates #male? to accessor' do
103
+ expect(accessor).to receive(:selected?).with(subject, 'male') { true }
104
+ expect(subject.male?).to be_true
105
+ end
106
+
107
+ it 'delegates #female? to accessor' do
108
+ expect(accessor).to receive(:selected?).with(subject, 'female') { false }
109
+ expect(subject.female?).to be_false
110
+ end
111
+
112
+ it 'delegates #male! to accessor' do
113
+ expect(accessor).to receive(:write).with(subject, 'male') { 0 }
114
+ expect(subject.male!).to eq 0
115
+ end
116
+
117
+ it 'delegates #female! to accessor' do
118
+ expect(accessor).to receive(:write).with(subject, 'female') { 1 }
119
+ expect(subject.female!).to eq 1
120
+ end
121
+ end
122
+
123
+ context 'with a prefix' do
124
+ fake_model(:klass_with_prefix) { as_enum :gender, %w{male female}, with: [:attribute], prefix: true }
125
+ subject { klass_with_prefix.new }
126
+
127
+ it 'delegates #gender? to accessor' do
128
+ expect(accessor).to receive(:selected?).with(subject, nil) { :female }
129
+ expect(subject.gender?).to be_true
130
+ end
131
+
132
+ it 'delegates #gender_male? to accessor' do
133
+ expect(accessor).to receive(:selected?).with(subject, 'male') { true }
134
+ expect(subject.gender_male?).to be_true
135
+ end
136
+
137
+ it 'delegates #gender_female? to accessor' do
138
+ expect(accessor).to receive(:selected?).with(subject, 'female') { false }
139
+ expect(subject.gender_female?).to be_false
140
+ end
141
+
142
+ it 'delegates #gender_male! to accessor' do
143
+ expect(accessor).to receive(:write).with(subject, 'male') { 0 }
144
+ expect(subject.gender_male!).to eq 0
145
+ end
146
+
147
+ it 'delegates #gender_female! to accessor' do
148
+ expect(accessor).to receive(:write).with(subject, 'female') { 1 }
149
+ expect(subject.gender_female!).to eq 1
150
+ end
151
+ end
152
+ end
153
+
154
+ context 'generate_enum_scope_methods_for', active_record: true do
155
+ fake_active_record(:klass) {
156
+ as_enum :gender, [:male, :female], with: [:scope]
157
+ }
158
+
159
+ shared_examples_for 'returning a relation' do |value|
160
+ it 'returns an ActiveRecord::Relation' do
161
+ expect(subject).to be_a(ActiveRecord::Relation)
162
+ end
163
+
164
+ it "queries for gender_cd = #{value}" do
165
+ values_hash = { "gender_cd" => value }
166
+ expect(subject.where_values_hash).to eq values_hash
167
+ end
168
+ end
169
+
170
+ context '.male' do
171
+ subject { klass.male }
172
+ it_behaves_like 'returning a relation', 0
173
+ end
174
+
175
+ context '.female' do
176
+ subject { klass.female }
177
+ it_behaves_like 'returning a relation', 1
178
+ end
179
+
180
+ context 'with prefix' do
181
+ fake_active_record(:klass) {
182
+ as_enum :gender, [:male, :female], with: [:scope], prefix: true
183
+ }
184
+
185
+ context '.gender_male' do
186
+ subject { klass.gender_male }
187
+ it_behaves_like 'returning a relation', 0
188
+ end
189
+
190
+ context '.gender_female' do
191
+ subject { klass.gender_female }
192
+ it_behaves_like 'returning a relation', 1
193
+ end
194
+ end
195
+
196
+ context 'without scope method' do
197
+ fake_model(:klass_without_scope_method) {
198
+ as_enum :gender, [:male, :female], with: [:scope]
199
+ }
200
+ subject { klass_without_scope_method }
201
+
202
+ it 'does not add .male nor .female' do
203
+ expect(subject).to_not respond_to(:male)
204
+ expect(subject).to_not respond_to(:female)
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleEnum::Enum do
4
+ let(:hash) do
5
+ { "male" => 0, "female" => 1 }
6
+ end
7
+
8
+ fake_model(:klass)
9
+ let(:object) { klass.new }
10
+
11
+ subject { described_class.new(:gender, hash) }
12
+
13
+ context '#name' do
14
+ it 'returns the enum name as string' do
15
+ expect(subject.name).to eq 'gender'
16
+ end
17
+ end
18
+
19
+ context '#to_s' do
20
+ it 'returns the name' do
21
+ expect(subject.to_s).to eq 'gender'
22
+ end
23
+ end
24
+
25
+ context '#hash' do
26
+ subject { described_class.new(:gender, hash).hash }
27
+
28
+ it 'returns hash that was set in the constructor' do
29
+ expect(subject).to be_a(Hash)
30
+ expect(subject.keys).to eq %w{male female}
31
+ expect(subject.values).to eq [0, 1]
32
+ end
33
+ end
34
+
35
+ context '#each_pair (aliased to #each)' do
36
+ it 'yields twice with #each_pair' do
37
+ expect { |b| subject.each_pair(&b) }.to yield_control.exactly(2).times
38
+ end
39
+
40
+ it 'yields twice with #each' do
41
+ expect { |b| subject.each(&b) }.to yield_control.exactly(2).times
42
+ end
43
+ end
44
+
45
+ context '#value (aliased to #[])' do
46
+ it 'looks up by string' do
47
+ expect(subject.value('male')).to eq 0
48
+ expect(subject['male']).to eq 0
49
+ end
50
+
51
+ it 'looks up by symbol' do
52
+ expect(subject.value(:female)).to eq 1
53
+ expect(subject[:female]).to eq 1
54
+ end
55
+
56
+ it 'looks up by value' do
57
+ expect(subject.value(0)).to be 0
58
+ expect(subject[0]).to be 0
59
+ end
60
+
61
+ it 'returns nil when key is not found' do
62
+ expect(subject.value(:inexistent)).to be_nil
63
+ expect(subject[:inexistent]).to be_nil
64
+ end
65
+ end
66
+
67
+ context '#key' do
68
+ it 'returns symbolized key for supplied value' do
69
+ expect(subject.key(0)).to eq :male
70
+ expect(subject.key(1)).to eq :female
71
+ end
72
+
73
+ it 'returns nil if value is not found' do
74
+ expect(subject.key(12)).to be_nil
75
+ end
76
+ end
77
+
78
+ context '#include?' do
79
+ it 'returns true by string' do
80
+ expect(subject.include?('male')).to be_true
81
+ end
82
+
83
+ it 'returns true by symbol' do
84
+ expect(subject.include?(:female)).to be_true
85
+ end
86
+
87
+ it 'returns true by checking actual value' do
88
+ expect(subject.include?(1)).to be_true
89
+ end
90
+
91
+ it 'returns false when neither in keys nor values' do
92
+ expect(subject.include?(:other)).to be_false
93
+ expect(subject.include?(2)).to be_false
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'simple_enum/hasher'
3
+
4
+ describe SimpleEnum::Hasher do
5
+ subject { described_class }
6
+
7
+ context '.map' do
8
+ subject { described_class.map(%w{male female}, map: :string) }
9
+
10
+ it 'uses DefaultHasher by default' do
11
+ result = { "male" => 0, "female" => 1 }
12
+ expect(described_class.map(%w{male female})).to eq result
13
+ end
14
+
15
+ it 'returns a frozen Hash' do
16
+ expect(subject).to be_a(Hash)
17
+ expect(subject).to be_frozen
18
+ end
19
+
20
+ it 'uses the builder supplied if available' do
21
+ result = { "male" => "male", "female" => "female" }
22
+ expect(subject).to eq result
23
+ end
24
+
25
+ it 'accepts a Proc as well' do
26
+ proc = ->(hash) { { "static" => 1 } }
27
+ result = { "static" => 1 }
28
+ expect(described_class.map(%w{male female}, map: proc) ).to eq result
29
+ end
30
+ end
31
+
32
+ context 'DefaultHasher.call' do
33
+ let(:result) do; { "male" => 0, "female" => 1 } end
34
+
35
+ it 'returns string => index for Array of strings' do
36
+ expect(subject::DefaultHasher.call(%w{male female})).to eq result
37
+ end
38
+
39
+ it 'returns string => index for Array of symbols' do
40
+ expect(subject::DefaultHasher.call([:male, :female])).to eq result
41
+ end
42
+
43
+ it 'returns string => number for Hash with symbolized keys' do
44
+ expect(subject::DefaultHasher.call(male: 0, female: 1)).to eq result
45
+ end
46
+
47
+ it 'returns string => number for hash with string keys' do
48
+ expect(subject::DefaultHasher.call('male' => 0, 'female' => 1)).to eq result
49
+ end
50
+ end
51
+
52
+ context 'StringHasher.call' do
53
+ let(:result) do; { "male" => "male", "female" => "female" } end
54
+
55
+ it 'retuns string => string for Array of strings' do
56
+ expect(subject::StringHasher.call(%w{male female})).to eq result
57
+ end
58
+
59
+ it 'returns string => string for Array of symbols' do
60
+ expect(subject::StringHasher.call([:male, :female])).to eq result
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'simple_enum/mongoid'
3
+
4
+ describe SimpleEnum::Mongoid, mongoid: true do
5
+ fake_mongoid_model(:klass) {
6
+ as_enum :gender, %w{male female}
7
+ }
8
+
9
+ let(:field) { klass.fields['gender_cd'] }
10
+
11
+ context '.as_enum' do
12
+ subject { klass }
13
+
14
+ it 'has the genders enum' do
15
+ expect(klass.genders).to be_a(SimpleEnum::Enum)
16
+ end
17
+
18
+ it 'creates the :gender_cd field' do
19
+ expect(field).to_not be_nil
20
+ expect(field.type).to eq Object
21
+ end
22
+
23
+ context 'field: { type: Integer }' do
24
+ fake_mongoid_model(:klass) {
25
+ as_enum :gender, %w{male female}, field: { type: Integer }
26
+ }
27
+
28
+ it 'creates the :gender_cd field as Integer' do
29
+ expect(field).to_not be_nil
30
+ expect(field.type).to eq Integer
31
+ end
32
+ end
33
+
34
+ context 'field: false' do
35
+ fake_mongoid_model(:klass) {
36
+ as_enum :gender, %w{male female}, field: false
37
+ }
38
+
39
+ it 'does not create the field' do
40
+ expect(field).to be_nil
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleEnum::Translation do
4
+ context '.human_enum_name', i18n: true do
5
+ fake_model(:klass) { extend SimpleEnum::Translation }
6
+ subject { klass }
7
+
8
+ shared_examples_for 'translating gender' do
9
+ it 'translates :male to "Mr."' do
10
+ expect(subject.human_enum_name(:gender, :male)).to eq 'Mr.'
11
+ end
12
+
13
+ it 'translates :female to "Mrs."' do
14
+ expect(subject.human_enum_name(:gender, :female)).to eq 'Mrs.'
15
+ end
16
+ end
17
+
18
+ context '{i18n_scope}.enums.{i18n_key}.gender.{key}' do
19
+ before do
20
+ store_translations :en, 'activemodel' => {
21
+ 'enums' => {
22
+ 'fake_model' => {
23
+ 'gender' => { 'male' => 'Mr.', 'female' => 'Mrs.' }
24
+ }
25
+ }
26
+ }
27
+ end
28
+
29
+ it_behaves_like 'translating gender'
30
+ end
31
+
32
+ context 'enums.{i18n_key}.gender.{key}' do
33
+ before do
34
+ store_translations :en, 'enums' => {
35
+ 'fake_model' => {
36
+ 'gender' => { 'male' => 'Mr.', 'female' => 'Mrs.' }
37
+ }
38
+ }
39
+ end
40
+
41
+ it_behaves_like 'translating gender'
42
+ end
43
+
44
+ context 'enums.gender.{key}' do
45
+ before do
46
+ store_translations :en, 'enums' => {
47
+ 'gender' => { 'male' => 'Mr.', 'female' => 'Mrs.' }
48
+ }
49
+ end
50
+
51
+ it_behaves_like 'translating gender'
52
+ end
53
+
54
+ context 'uses :default if available' do
55
+ it 'translates :female to "Frau" using default:' do
56
+ expect(subject.human_enum_name(:gender, :female, default: 'Frau')).to eq 'Frau'
57
+ end
58
+ end
59
+
60
+ context 'falls back to titleize' do
61
+ it 'translates using .titleize if no translations found' do
62
+ expect(subject.human_enum_name(:gender, :female)).to eq 'Female'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'rspec'
5
+ require 'active_record'
6
+ require 'mongoid'
7
+
8
+ if ENV['CODECLIMATE_REPO_TOKEN']
9
+ require "codeclimate-test-reporter"
10
+ CodeClimate::TestReporter.start
11
+ end
12
+
13
+ require 'simple_enum'
14
+
15
+ require 'support/active_record_support'
16
+ require 'support/i18n_support'
17
+ require 'support/model_support'
18
+ require 'support/mongoid_support'
19
+
20
+ I18n.enforce_available_locales = false
21
+
22
+ RSpec.configure do |config|
23
+ config.include ModelSupport
24
+ config.include I18nSupport, i18n: true
25
+ config.include ActiveRecordSupport, active_record: true
26
+ config.include MongoidSupport, mongoid: true
27
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveRecordSupport
2
+ def self.connection
3
+ @connection_pool ||= ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
4
+ ActiveRecord::Base.connection
5
+ end
6
+
7
+ def self.included(base)
8
+ base.before(:each) { self.reset_active_record }
9
+ end
10
+
11
+ def reset_active_record
12
+ ActiveRecordSupport.connection.create_table :dummies, :force => true do |t|
13
+ t.column :name, :string
14
+ t.column :gender_cd, :integer
15
+ t.column :word_cd, :string, :limit => 5
16
+ t.column :role_cd, :string
17
+ t.column :other, :integer
18
+ t.column :numeric_cd, :string
19
+ t.column :nilish_cd, :string
20
+ t.column :style_cd, :integer
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module I18nSupport
2
+ def self.included(base)
3
+ base.let!(:i18n_previous_backend) { I18n.backend }
4
+ base.let(:i18n_backend) { I18n::Backend::KeyValue.new({}) }
5
+ base.before { I18n.backend = i18n_backend }
6
+ base.after { I18n.backend = i18n_previous_backend }
7
+ end
8
+
9
+ def store_translations(lang, translations)
10
+ i18n_backend.store_translations lang, translations
11
+ end
12
+ end
@@ -0,0 +1,47 @@
1
+ require 'active_record'
2
+ require 'mongoid'
3
+
4
+ module ModelSupport
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def fake_active_record(name, &block)
12
+ let(name) {
13
+ Class.new(ActiveRecord::Base) do
14
+ self.table_name = 'dummies'
15
+ instance_eval &block
16
+ end
17
+ }
18
+ end
19
+
20
+ def fake_mongoid_model(name, &block)
21
+ let(name) {
22
+ Class.new do
23
+ include Mongoid::Document
24
+ include SimpleEnum::Mongoid
25
+
26
+ store_in collection: 'dummies'
27
+ instance_eval &block
28
+ end
29
+ }
30
+ end
31
+
32
+ def fake_model(name, *fields, &block)
33
+ fields << :gender_cd
34
+ let(name) {
35
+ Struct.new(*fields) do
36
+ extend ActiveModel::Translation
37
+ extend SimpleEnum::Attribute
38
+ instance_eval &block if block_given?
39
+
40
+ def self.model_name
41
+ @model_name ||= ActiveModel::Name.new(self, nil, "FakeModel")
42
+ end
43
+ end
44
+ }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ require 'mongoid'
2
+
3
+ module MongoidSupport
4
+ def self.connection
5
+ @connection ||= begin
6
+ Mongoid.configure.connect_to("simple_enum_mongoid_test")
7
+ Mongoid.default_session.options[:max_retries] = 0
8
+ end
9
+ Mongoid.default_session
10
+ end
11
+
12
+ def self.included(base)
13
+ base.before {
14
+ begin
15
+ MongoidSupport.connection.collection_names
16
+ rescue Moped::Errors::ConnectionFailure
17
+ pending "Start MongoDB server to run Mongoid integration tests..."
18
+ end
19
+ }
20
+ end
21
+ end