mongoid-enum-dazzl 1.0.0.pre.853362636

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.
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: []