mongoid-enum-dazzl 1.0.0.pre.853362636

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ae85a8cca8495c314aaa21826a3f59cfd184912d2f247daffa25e7d41243a093
4
+ data.tar.gz: 6fda92281990a7dd6e5af95201c6afe6435e854929aab6d03846597229ca6590
5
+ SHA512:
6
+ metadata.gz: cb9f3a5f53713d58be29147e6c43ce96833ee36a6d71532bcf7bd4676f21b50e9527fa64da7a42d9fbb8ab01cca1765294730a6f704a0debfddb68ad794c0e0b
7
+ data.tar.gz: 9ec4d9a9f18868beb6dd9a1b952fba9f3c6aa68823acb7b67350112f99ca60b72daa7ee574cbaa95eae22b205a6961f6ed3c33975a84062e66fd88aabae8f368
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in mongoid-enum.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2021 Dazzl
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # Mongoid::Enum
2
+ [![RSpec](https://github.com/dazzl-tv/mongoid-enum/actions/workflows/rspec.yml/badge.svg?branch=develop&event=pull_request)](https://github.com/dazzl-tv/mongoid-enum/actions/workflows/rspec.yml)
3
+ [![Linter](https://github.com/dazzl-tv/mongoid-enum/actions/workflows/linter.yml/badge.svg)](https://github.com/dazzl-tv/mongoid-enum/actions/workflows/linter.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/mongoid-enum.svg)](https://badge.fury.io/rb/mongoid-enum)
5
+ [![Docs](https://inch-ci.org/github/dazzl-tv/mongoid-enum.svg)](https://inch-ci.org/github/dazzl-tv/mongoid-enum)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/34c8fdc8181220e50ff7/maintainability)](https://codeclimate.com/github/dazzl-tv/mongoid-enum/maintainability)
7
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/34c8fdc8181220e50ff7/test_coverage)](https://codeclimate.com/github/dazzl-tv/mongoid-enum/test_coverage)
8
+
9
+ Heavily inspired by [DHH's
10
+ ActiveRecord::Enum](https://github.com/rails/rails/commit/db41eb8a6ea88b854bf5cd11070ea4245e1639c5), this little library is
11
+ there to help you cut down the cruft in your models and make the
12
+ world a happier place at the same time.
13
+
14
+ A single line will get you fields, accessors, validations and scopes,
15
+ and a few other bits-and-bobs.
16
+
17
+
18
+ # Installation
19
+
20
+ Add this to your Gemfile:
21
+
22
+ ```ruby
23
+ gem "mongoid-enum"
24
+ ```
25
+
26
+ And then run `bundle install`.
27
+
28
+
29
+ # Usage
30
+
31
+ ```ruby
32
+ class Payment
33
+ include Mongoid::Document
34
+ include Mongoid::Enum
35
+
36
+ enum :status, [:pending, :approved, :declined]
37
+ end
38
+ ```
39
+
40
+ Aaaaaaand then you get things like:
41
+
42
+ ```ruby
43
+ payment = Payment.create
44
+
45
+ payment.status
46
+ # => :pending
47
+
48
+ payment.approved!
49
+ # => :approved
50
+
51
+ payment.pending?
52
+ # => :false
53
+
54
+ Payment.approved
55
+ # => Mongoid::Criteria for payments with status == :approved
56
+
57
+ ```
58
+
59
+ # Features
60
+
61
+ ## Field
62
+
63
+ Your enum value is stored as either a Symbol, or an Array (when storing
64
+ multiple values). The actual field name has a leading underscore (e.g.:
65
+ `_status`), but is also aliased with its actual name for you
66
+ convenience.
67
+
68
+
69
+ ## Accessors
70
+
71
+ Your enums will get getters-and-setters with the same name. So using the
72
+ `Payment` example above:
73
+
74
+ ```ruby
75
+ payment.status = :declined
76
+ payment.status
77
+ # => :declined
78
+ ```
79
+
80
+ And you also get bang(!) and query(?) methods for each of the values in
81
+ your enum (see [this example](#usage).
82
+
83
+
84
+ ## Constants
85
+
86
+ For each enum, you'll also get a constant named after it. This is to
87
+ help you elsewhere in your app, should you need to display, or leverage
88
+ the list of values. Using the above example:
89
+
90
+ ```ruby
91
+ Payment::STATUS
92
+ # => [:pending, :approved, :declined]
93
+ ```
94
+
95
+
96
+ ## Validations
97
+
98
+ Enum values are automatically validated against the list. You can
99
+ disable this behaviour (see [below](#options)).
100
+
101
+
102
+ ## Scopes
103
+
104
+ A scope added for each of your enum's values. Using the example above,
105
+ you'd automatically get:
106
+
107
+ ```ruby
108
+ Payment.pending # => Mongoid::Criteria
109
+ Payment.approved # => Mongoid::Criteria
110
+ Payment.declined # => Mongoid::Criteria
111
+ ```
112
+
113
+
114
+ # Options
115
+
116
+ ## Default value
117
+
118
+ If not specified, the default will be the first in your list of values
119
+ (`:pending` in the example above). You can override this with the
120
+ `:default` option:
121
+
122
+ ```ruby
123
+ enum :roles, [:manager, :administrator], :default => ""
124
+ ```
125
+
126
+ ## Multiple values
127
+
128
+ Sometimes you'll need to store multiple values from your list, this
129
+ couldn't be easier:
130
+
131
+ ```ruby
132
+ enum :roles, [:basic, :manager, :administrator], :multiple => true
133
+
134
+ # ...
135
+
136
+ user = User.create
137
+ user.roles << :basic
138
+ user.roles << :manager
139
+ user.save!
140
+
141
+ user.manager? # => true
142
+ user.administrator? # => false
143
+ user.roles # => [:basic, :manager]
144
+ ```
145
+
146
+ Since the underlying datatype for storing values is an array, if you
147
+ need to specify default(s), ensure you use an array:
148
+
149
+ ```ruby
150
+ enum :roles, [:noob, :author, :editor], :multiple => true, :default => [:author, :editor] # two defaults
151
+ enum :roles, [:noob, :author, :editor], :multiple => true, :default => [] # no default
152
+ ```
153
+
154
+ ## Validations
155
+
156
+ Validations are baked in by default, and ensure that the value(s) set in
157
+ your field are always from your list of options. If you need more
158
+ complex validations, or you just want to throw caution to the wind, you
159
+ can turn them off:
160
+
161
+ ```ruby
162
+ enum :status, [:up, :down], :validate => false
163
+ ```
164
+
165
+ # Issues and Feature Requests
166
+
167
+ If you have any problems, or you have a suggestion, please [submit an
168
+ issue](https://github.com/thetron/mongoid-enum/issues) (and a failing
169
+ test, if you can). Pull requests and feature requests are alwasy welcome
170
+ and greatly appreciated.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid/enum/dazzl/info'
4
+ require 'mongoid/enum/dazzl/validators/multiple_validator'
5
+ require 'mongoid/enum/dazzl/configuration'
6
+
7
+ module Mongoid
8
+ module Enum
9
+ module Dazzl
10
+ extend ActiveSupport::Concern
11
+ module ClassMethods
12
+ def enum(name, values, options = {})
13
+ field_name = :"#{Mongoid::Enum::Dazzl.configuration.field_name_prefix}#{name}"
14
+ options = default_options(values).merge(options)
15
+
16
+ set_values_constant name, values
17
+
18
+ create_field field_name, options
19
+
20
+ create_validations field_name, values, options
21
+ define_value_scopes_and_accessors field_name, values, options
22
+ define_field_accessor name, field_name, options
23
+ end
24
+
25
+ private
26
+
27
+ def default_options(values)
28
+ {
29
+ multiple: false,
30
+ default: values.first,
31
+ required: true,
32
+ validate: true
33
+ }
34
+ end
35
+
36
+ def set_values_constant(name, values)
37
+ const_name = name.to_s.upcase
38
+ const_set const_name, values
39
+ end
40
+
41
+ def create_field(field_name, options)
42
+ type = options[:multiple] && Array || Symbol
43
+ field field_name, type: type, default: options[:default]
44
+ end
45
+
46
+ def create_validations(field_name, values, options)
47
+ if options[:multiple] && options[:validate]
48
+ validates field_name,
49
+ 'mongoid/enum/dazzl/validators/multiple': {
50
+ in: values.map(&:to_sym),
51
+ allow_nil: !options[:required]
52
+ }
53
+
54
+ # FIXME: Shouldn't this be `elsif options[:validate]` ???
55
+ elsif validate
56
+ validates field_name,
57
+ inclusion: { in: values.map(&:to_sym) },
58
+ allow_nil: !options[:required]
59
+ end
60
+ end
61
+
62
+ def define_value_scopes_and_accessors(field_name, values, options)
63
+ values.each do |value|
64
+ scope value, -> { where(field_name => value) }
65
+
66
+ if options[:multiple]
67
+ define_array_accessor(field_name, value)
68
+ else
69
+ define_string_accessor(field_name, value)
70
+ end
71
+ end
72
+ end
73
+
74
+ def define_field_accessor(name, field_name, options)
75
+ if options[:multiple]
76
+ define_array_field_accessor name, field_name
77
+ else
78
+ define_string_field_accessor name, field_name
79
+ end
80
+ end
81
+
82
+ def define_array_field_accessor(name, field_name)
83
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
84
+ def #{name}=(vals)
85
+ self.write_attribute(:#{field_name},
86
+ Array(vals).compact.map(&:to_sym))
87
+ end
88
+
89
+ def #{name}()
90
+ self.read_attribute(:#{field_name})
91
+ end
92
+ EOT
93
+ end
94
+
95
+ def define_string_field_accessor(name, field_name)
96
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
97
+ def #{name}=(val)
98
+ self.write_attribute(:#{field_name},
99
+ val && val.to_sym || nil)
100
+ end
101
+
102
+ def #{name}()
103
+ self.read_attribute(:#{field_name})
104
+ end
105
+ EOT
106
+ end
107
+
108
+ def define_array_accessor(field_name, value)
109
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
110
+ def #{value}?()
111
+ self.#{field_name}.include?(:#{value})
112
+ end
113
+
114
+ def #{value}!()
115
+ update_attributes! \
116
+ :#{field_name} => (self.#{field_name} || []) + [:#{value}]
117
+ end
118
+ EOT
119
+ end
120
+
121
+ def define_string_accessor(field_name, value)
122
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
123
+ def #{value}?()
124
+ self.#{field_name} == :#{value}
125
+ end
126
+
127
+ def #{value}!()
128
+ update_attributes! :#{field_name} => :#{value}
129
+ end
130
+ EOT
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Enum
5
+ module Dazzl
6
+ class Configuration
7
+ attr_accessor :field_name_prefix
8
+
9
+ def initialize
10
+ self.field_name_prefix = '_'
11
+ end
12
+ end
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration) if block_given?
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Define constant to gem
4
+ module Mongoid
5
+ module Enum
6
+ module Dazzl
7
+ # Define version to gem
8
+ # module Dazzl
9
+ VERSION = '1.0.0'
10
+
11
+ # Name to gem
12
+ GEM_NAME = 'mongoid-enum-dazzl'
13
+
14
+ # Authors
15
+ AUTHORS = ['VAILLANT Jeremy'].freeze
16
+
17
+ # Emails
18
+ EMAILS = ['jeremy@dazzl.tv'].freeze
19
+
20
+ # Licence
21
+ LICENSE = 'MIT'
22
+
23
+ # Define a summary description to gem
24
+ SUMMARY = 'Sweet enum sugar for your Mongoid documents'
25
+
26
+ # Define a long description to gem
27
+ DESCRIPTION = <<-DESC
28
+ Heavily inspired by DDH's ActiveRecord::Enum, this little library is
29
+ there to help you cut down the cruft in your models and make
30
+ the world a happier place at the same time.
31
+ DESC
32
+
33
+ # Homepage to project
34
+ HOMEPAGE = 'https://github.com/dazzl-tv/mongoid-enum'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ module Enum
5
+ module Dazzl
6
+ module Validators
7
+ class MultipleValidator < ActiveModel::EachValidator
8
+ def validate_each(record, attribute, values)
9
+ values = Array(values)
10
+
11
+ if options[:allow_nil]
12
+ add_error_message record, attribute \
13
+ unless all_included?(values, options[:in])
14
+ elsif values.empty? || !all_included?(values, options[:in])
15
+ add_error_message record, attribute
16
+ end
17
+ end
18
+
19
+ def add_error_message(record, attribute)
20
+ record.errors[attribute] << (
21
+ options[:message] ||
22
+ "is not in #{options[:in].join ', '}"
23
+ )
24
+ end
25
+
26
+ def all_included?(values, allowed)
27
+ (values - allowed).empty?
28
+ end
29
+
30
+ def self.kind
31
+ :custom
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Mongoid::Enum::Dazzl::Configuration do
6
+ subject(:conf) { described_class.new }
7
+
8
+ describe 'field_name_prefix' do
9
+ it "has '_' as default value" do
10
+ expect(conf.field_name_prefix).to eq '_'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'ostruct'
5
+
6
+ describe Mongoid::Enum::Dazzl::Validators::MultipleValidator do
7
+ subject { described_class }
8
+
9
+ let(:values) { %i[lorem ipsum dolor sit] }
10
+ let(:attribute) { :word }
11
+ let(:record) { OpenStruct.new(:errors => { attribute => [] }, attribute => values.first) }
12
+ let(:allow_nil) { false }
13
+ let(:validator) { subject.new(attributes: attribute, in: values, allow_nil: allow_nil) }
14
+
15
+ describe '.validate_each' do
16
+ context 'when allow_nil: true' do
17
+ let(:allow_nil) { true }
18
+
19
+ context 'with value is nil' do
20
+ before { validator.validate_each(record, attribute, nil) }
21
+
22
+ it 'validates' do
23
+ expect(record.errors[attribute].empty?).to be true
24
+ end
25
+ end
26
+
27
+ context 'with value is []' do
28
+ before { validator.validate_each(record, attribute, []) }
29
+
30
+ it 'validates' do
31
+ expect(record.errors[attribute].empty?).to be true
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'when allow_nil: false' do
37
+ context 'with value is nil' do
38
+ before { validator.validate_each(record, attribute, nil) }
39
+
40
+ it "won't validate (true)" do
41
+ expect(record.errors[attribute].any?).to be true
42
+ end
43
+
44
+ it "won't validate (equal)" do
45
+ expect(record.errors[attribute]).to eq ["is not in #{values.join ', '}"]
46
+ end
47
+ end
48
+
49
+ context 'with value is []' do
50
+ before { validator.validate_each(record, attribute, []) }
51
+
52
+ it "won't validate (true)" do
53
+ expect(record.errors[attribute].any?).to be true
54
+ end
55
+
56
+ it "won't validate (equal)" do
57
+ expect(record.errors[attribute]).to eq ["is not in #{values.join ', '}"]
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'when value is included' do
63
+ let(:allow_nil) { rand(2).zero? }
64
+
65
+ before { validator.validate_each(record, attribute, [values.sample]) }
66
+
67
+ it 'validates' do
68
+ expect(record.errors[attribute].empty?).to be true
69
+ end
70
+ end
71
+
72
+ context 'when value is not included' do
73
+ let(:allow_nil) { rand(2).zero? }
74
+
75
+ before { validator.validate_each(record, attribute, [:amet]) }
76
+
77
+ it "won't validate" do
78
+ expect(record.errors[attribute].any?).to be true
79
+ end
80
+ end
81
+
82
+ context 'when multiple values included' do
83
+ let(:allow_nil) { rand(2).zero? }
84
+
85
+ before { validator.validate_each(record, attribute, [values.first, values.last]) }
86
+
87
+ it 'validates' do
88
+ expect(record.errors[attribute].empty?).to be true
89
+ end
90
+ end
91
+
92
+ context 'when one value is not included ' do
93
+ let(:allow_nil) { rand(2).zero? }
94
+
95
+ before { validator.validate_each(record, attribute, [values.first, values.last, :amet]) }
96
+
97
+ it "won't validate" do
98
+ expect(record.errors[attribute].any?).to be true
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,297 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'mongoid/enum/dazzl/configuration'
5
+
6
+ class User
7
+ include Mongoid::Document
8
+ include Mongoid::Enum::Dazzl
9
+
10
+ enum :status, %i[awaiting_approval approved banned]
11
+ enum :roles, %i[author editor admin], multiple: true, default: [], required: false
12
+ end
13
+
14
+ # rubocop:disable RSpec/LeakyConstantDeclaration, Lint/ConstantDefinitionInBlock
15
+ describe Mongoid::Enum::Dazzl do
16
+ let(:klass) { User }
17
+ let(:instance) { User.new }
18
+ let(:alias_name) { :status }
19
+ let(:field_name) { :"_#{alias_name}" }
20
+ let(:values) { %i[awaiting_approval approved banned] }
21
+ let(:multiple_field_name) { :_roles }
22
+
23
+ describe 'field' do
24
+ it 'is defined' do
25
+ expect(klass).to have_field(field_name)
26
+ end
27
+
28
+ # rubocop:disable RSpec/ExampleLength
29
+ it 'uses prefix defined in configuration' do
30
+ old_field_name_prefix = described_class.configuration.field_name_prefix
31
+ described_class.configure do |config|
32
+ config.field_name_prefix = '___'
33
+ end
34
+
35
+ UserWithoutPrefix = Class.new do
36
+ include Mongoid::Document
37
+ include Mongoid::Enum::Dazzl
38
+
39
+ enum :status, %i[awaiting_approval approved banned]
40
+ end
41
+
42
+ expect(UserWithoutPrefix).to have_field '___status'
43
+ described_class.configure do |config|
44
+ config.field_name_prefix = old_field_name_prefix
45
+ end
46
+ end
47
+ # rubocop:enable RSpec/ExampleLength
48
+
49
+ it 'is aliased' do
50
+ expect(instance).to respond_to alias_name
51
+ end
52
+
53
+ it 'is :aliased=' do
54
+ expect(instance).to respond_to :"#{alias_name}="
55
+ end
56
+
57
+ it 'is :aliased' do
58
+ expect(instance).to respond_to :"#{alias_name}"
59
+ end
60
+
61
+ describe 'type' do
62
+ context 'when multiple' do
63
+ it 'is an array' do
64
+ expect(klass).to have_field(multiple_field_name).of_type(Array)
65
+ end
66
+
67
+ it 'validates using a custom validator' do
68
+ expect(klass).to custom_validate(multiple_field_name).with_validator(described_class::Validators::MultipleValidator)
69
+ end
70
+ end
71
+
72
+ context 'when not multiple' do
73
+ it 'is a symbol' do
74
+ expect(klass).to have_field(field_name).of_type(Symbol)
75
+ end
76
+
77
+ it 'validates inclusion in values' do
78
+ expect(klass).to validate_inclusion_of(field_name).to_allow(values)
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "'required' option" do
85
+ context 'when true' do
86
+ let(:instance) { User.new status: nil }
87
+
88
+ it 'is not valid with nil value' do
89
+ expect(instance).not_to be_valid
90
+ end
91
+ end
92
+
93
+ context 'when false' do
94
+ let(:instance) { User.new roles: nil }
95
+
96
+ it 'is valid with nil value' do
97
+ expect(instance).to be_valid
98
+ end
99
+ end
100
+ end
101
+
102
+ describe 'constant' do
103
+ it 'is set to the values' do
104
+ expect(klass::STATUS).to eq values
105
+ end
106
+ end
107
+
108
+ describe 'accessors' do
109
+ context 'when singular' do
110
+ describe 'setter' do
111
+ it 'accepts strings' do
112
+ instance.status = 'banned'
113
+ expect(instance.status).to eq :banned
114
+ end
115
+
116
+ it 'accepts symbols' do
117
+ instance.status = :banned
118
+ expect(instance.status).to eq :banned
119
+ end
120
+ end
121
+
122
+ describe '{{value}}!' do
123
+ it 'sets the value' do
124
+ instance.save
125
+ instance.banned!
126
+ expect(instance.status).to eq :banned
127
+ end
128
+ end
129
+
130
+ describe '{{value}}?' do
131
+ context 'when {{enum}} == {{value}}' do
132
+ it 'returns true' do
133
+ instance.save
134
+ instance.banned!
135
+ expect(instance.banned?).to eq true
136
+ end
137
+ end
138
+
139
+ context 'when {{enum}} != {{value}}' do
140
+ it 'returns false' do
141
+ instance.save
142
+ instance.banned!
143
+ expect(instance.approved?).to eq false
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ context 'when multiple' do
150
+ describe 'setter' do
151
+ it 'accepts strings' do
152
+ instance.roles = 'author'
153
+ expect(instance.roles).to eq [:author]
154
+ end
155
+
156
+ it 'accepts symbols' do
157
+ instance.roles = :author
158
+ expect(instance.roles).to eq [:author]
159
+ end
160
+
161
+ it 'accepts arrays of strings' do
162
+ instance.roles = %w[author editor]
163
+ instance.save
164
+ puts instance.errors.full_messages
165
+ instance.reload
166
+ expect(instance.roles).to include(:author, :editor)
167
+ end
168
+
169
+ it 'accepts arrays of symbols' do
170
+ instance.roles = %i[author editor]
171
+
172
+ expect(instance.roles).to include(:author, :editor)
173
+ end
174
+ end
175
+
176
+ describe '{{value}}!' do
177
+ context 'when field is nil' do
178
+ it 'creates an array containing the value' do
179
+ instance.roles = nil
180
+ instance.save
181
+ instance.author!
182
+ expect(instance.roles).to eq [:author]
183
+ end
184
+ end
185
+
186
+ context 'when field is not nil' do
187
+ it 'appends the value' do
188
+ instance.save
189
+ instance.author!
190
+ instance.editor!
191
+ expect(instance.roles).to eq %i[author editor]
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '{{value}}?' do
197
+ context 'when {{enum}} contains {{value}}' do
198
+ before do
199
+ instance.save
200
+ instance.author!
201
+ instance.editor!
202
+ end
203
+
204
+ it 'editor? returns true' do
205
+ expect(instance.editor?).to be true
206
+ end
207
+
208
+ it 'author? returns true' do
209
+ expect(instance.author?).to be true
210
+ end
211
+ end
212
+
213
+ context 'when {{enum}} does not contain {{value}}' do
214
+ it 'returns false' do
215
+ instance.save
216
+ expect(instance.author?).to be false
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ describe 'scopes' do
224
+ context 'when singular' do
225
+ it 'returns the corresponding documents' do
226
+ instance.save
227
+ instance.banned!
228
+ expect(User.banned.to_a).to eq [instance]
229
+ end
230
+ end
231
+
232
+ context 'when multiple' do
233
+ context 'with only one document' do
234
+ it 'returns that document' do
235
+ instance.save
236
+ instance.author!
237
+ instance.editor!
238
+ expect(User.author.to_a).to eq [instance]
239
+ end
240
+ end
241
+
242
+ context 'with more than one document' do
243
+ before do
244
+ instance.save
245
+ instance.author!
246
+ instance.editor!
247
+ end
248
+
249
+ it 'returns all author documents with those values' do
250
+ instance2 = klass.create
251
+ instance2.author!
252
+
253
+ expect(User.author.to_a).to eq [instance, instance2]
254
+ end
255
+
256
+ it 'returns all editor documents with those values' do
257
+ expect(User.editor.to_a).to eq [instance]
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ describe 'default values' do
264
+ context 'when not specified' do
265
+ it 'uses the first value' do
266
+ instance.save
267
+ expect(instance.status).to eq values.first
268
+ end
269
+ end
270
+
271
+ context 'when specified' do
272
+ it 'uses the specified value' do
273
+ instance.save
274
+ expect(instance.roles).to eq []
275
+ end
276
+ end
277
+ end
278
+
279
+ describe '.configuration' do
280
+ it 'returns Configuration object' do
281
+ expect(described_class.configuration)
282
+ .to be_instance_of described_class::Configuration
283
+ end
284
+
285
+ it 'returns same object when called multiple times' do
286
+ expect(described_class.configuration).to be described_class.configuration
287
+ end
288
+ end
289
+
290
+ describe '.configure' do
291
+ it 'yields configuration if block is given' do
292
+ expect { |b| described_class.configure(&b) }
293
+ .to yield_with_args described_class.configuration
294
+ end
295
+ end
296
+ end
297
+ # rubocop:enable RSpec/LeakyConstantDeclaration, Lint/ConstantDefinitionInBlock
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid'
4
+ require 'mongoid/rspec'
5
+ require 'mongoid/enum'
6
+ require 'simplecov'
7
+ require 'simplecov_json_formatter'
8
+
9
+ SimpleCov.start
10
+ SimpleCov.formatter = SimpleCov::Formatter::JSONFormatter
11
+
12
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
13
+
14
+ ENV['MONGOID_ENV'] = 'test'
15
+
16
+ RSpec.configure do |config|
17
+ config.include Mongoid::Matchers
18
+
19
+ config.before do
20
+ Mongoid.purge!
21
+ end
22
+
23
+ # Stop when rspec fail
24
+ config.fail_fast = true
25
+
26
+ # Exclude spec broken
27
+ config.filter_run_excluding broken: true
28
+ end
29
+
30
+ # Load mongoid configuration
31
+ Mongoid.load!(File.expand_path('support/mongoid.yml', __dir__), :test)
32
+ Mongo::Logger.logger.level = ::Logger::INFO
@@ -0,0 +1,6 @@
1
+ test:
2
+ clients:
3
+ default:
4
+ database: mongoid-enum_test
5
+ hosts:
6
+ - localhost:<%= ENV['BOXEN_MONGODB_PORT'] || 27017 %>
metadata ADDED
@@ -0,0 +1,279 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-enum-dazzl
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre.853362636
5
+ platform: ruby
6
+ authors:
7
+ - VAILLANT Jeremy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ - - "<="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.2.16
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.2'
30
+ - - "<="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.2.16
33
+ - !ruby/object:Gem::Dependency
34
+ name: faker
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.17'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.17'
47
+ - !ruby/object:Gem::Dependency
48
+ name: mongoid-rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '4.1'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '4.1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: pry-byebug
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.9'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.9'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '13.0'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 13.0.3
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '13.0'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 13.0.3
95
+ - !ruby/object:Gem::Dependency
96
+ name: reek
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: 6.0.4
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: 6.0.4
109
+ - !ruby/object:Gem::Dependency
110
+ name: rspec
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '3.10'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.10'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rubocop
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: 1.13.0
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: 1.13.0
137
+ - !ruby/object:Gem::Dependency
138
+ name: rubocop-faker
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '1.1'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '1.1'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rubocop-performance
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '1.11'
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: 1.11.1
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '1.11'
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: 1.11.1
171
+ - !ruby/object:Gem::Dependency
172
+ name: rubocop-rspec
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - "~>"
176
+ - !ruby/object:Gem::Version
177
+ version: '2.3'
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: '2.3'
185
+ - !ruby/object:Gem::Dependency
186
+ name: simplecov
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: 0.21.2
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - "~>"
197
+ - !ruby/object:Gem::Version
198
+ version: 0.21.2
199
+ - !ruby/object:Gem::Dependency
200
+ name: simplecov_json_formatter
201
+ requirement: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - "~>"
204
+ - !ruby/object:Gem::Version
205
+ version: 0.1.3
206
+ type: :development
207
+ prerelease: false
208
+ version_requirements: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - "~>"
211
+ - !ruby/object:Gem::Version
212
+ version: 0.1.3
213
+ - !ruby/object:Gem::Dependency
214
+ name: mongoid
215
+ requirement: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - "~>"
218
+ - !ruby/object:Gem::Version
219
+ version: '7.2'
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: 7.2.2
223
+ type: :runtime
224
+ prerelease: false
225
+ version_requirements: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '7.2'
230
+ - - ">="
231
+ - !ruby/object:Gem::Version
232
+ version: 7.2.2
233
+ description: |2
234
+ Heavily inspired by DDH's ActiveRecord::Enum, this little library is
235
+ there to help you cut down the cruft in your models and make
236
+ the world a happier place at the same time.
237
+ email:
238
+ - jeremy@dazzl.tv
239
+ executables: []
240
+ extensions: []
241
+ extra_rdoc_files: []
242
+ files:
243
+ - Gemfile
244
+ - LICENSE
245
+ - README.md
246
+ - Rakefile
247
+ - lib/mongoid/enum/dazzl.rb
248
+ - lib/mongoid/enum/dazzl/configuration.rb
249
+ - lib/mongoid/enum/dazzl/info.rb
250
+ - lib/mongoid/enum/dazzl/validators/multiple_validator.rb
251
+ - spec/mongoid/enum/dazzl/configuration_spec.rb
252
+ - spec/mongoid/enum/dazzl/validators/multiple_validator_spec.rb
253
+ - spec/mongoid/enum/dazzl_spec.rb
254
+ - spec/spec_helper.rb
255
+ - spec/support/mongoid.yml
256
+ homepage: https://github.com/dazzl-tv/mongoid-enum
257
+ licenses:
258
+ - MIT
259
+ metadata: {}
260
+ post_install_message:
261
+ rdoc_options: []
262
+ require_paths:
263
+ - lib
264
+ required_ruby_version: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - ">="
267
+ - !ruby/object:Gem::Version
268
+ version: 2.6.0
269
+ required_rubygems_version: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - ">"
272
+ - !ruby/object:Gem::Version
273
+ version: 1.3.1
274
+ requirements: []
275
+ rubygems_version: 3.0.3.1
276
+ signing_key:
277
+ specification_version: 4
278
+ summary: Sweet enum sugar for your Mongoid documents
279
+ test_files: []