flexible_enum 0.2.2
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 +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +5 -0
- data/Appraisals +7 -0
- data/CONTRIBUTING.md +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +295 -0
- data/Rakefile +4 -0
- data/flexible_enum.gemspec +32 -0
- data/gemfiles/rails_4.1.gemfile +7 -0
- data/gemfiles/rails_4.2.gemfile +7 -0
- data/lib/flexible_enum/abstract_configurator.rb +11 -0
- data/lib/flexible_enum/configuration.rb +20 -0
- data/lib/flexible_enum/constant_configurator.rb +11 -0
- data/lib/flexible_enum/mixin.rb +47 -0
- data/lib/flexible_enum/name_configurator.rb +44 -0
- data/lib/flexible_enum/potential_values_configurator.rb +45 -0
- data/lib/flexible_enum/question_method_configurator.rb +21 -0
- data/lib/flexible_enum/scope_configurator.rb +23 -0
- data/lib/flexible_enum/setter_method_configurator.rb +20 -0
- data/lib/flexible_enum/version.rb +3 -0
- data/lib/flexible_enum.rb +19 -0
- data/spec/constant_definition_spec.rb +16 -0
- data/spec/custom_options_spec.rb +7 -0
- data/spec/enum_introspection_spec.rb +9 -0
- data/spec/inheritance_spec.rb +16 -0
- data/spec/name_values_spec.rb +44 -0
- data/spec/potential_values_spec.rb +42 -0
- data/spec/predicate_methods_spec.rb +39 -0
- data/spec/scopes_spec.rb +27 -0
- data/spec/setter_methods_spec.rb +48 -0
- data/spec/spec_helper.rb +58 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a885917e4b7e8bb397a0dab1d78711395ab49120
|
4
|
+
data.tar.gz: b0baf4ab1c1bd0cfc3c337e5cc585c71043ff96f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc8c6c0dc01306ccff5e961de08e66457486b4ef8f3e8ba5a716e356c8ad1b69a5403e51a158f8690e5d3b9a426bfea74c5807791a5dab83dd00d3fca1a7abc3
|
7
|
+
data.tar.gz: da33ab81de96f8813b6cde44c4bafee0ec5b0de44a8f87749c0a2661a2464ca80d626648f6fb9ef31f0af41901d33267b5aafbff7caeea359bc669769e0caf2f
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Appraisals
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Contributing to FlexibleEnum
|
2
|
+
|
3
|
+
By participating in this project, you agree to abide by the MeYou Health [code of conduct].
|
4
|
+
|
5
|
+
[code of conduct]: http://engineering.meyouhealth.com/open-source/code-of-conduct
|
6
|
+
|
7
|
+
To contribute to FlexibleEnum:
|
8
|
+
|
9
|
+
1. Fork it
|
10
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
11
|
+
3. Run the tests (`appraisal rspec`)
|
12
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
13
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
14
|
+
6. Create new Pull Request
|
15
|
+
|
16
|
+
Want more detail on these steps? [Learn more about forking git
|
17
|
+
repositories](https://guides.github.com/activities/forking/).
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013–2015 MeYou Health
|
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,295 @@
|
|
1
|
+
# FlexibleEnum
|
2
|
+
|
3
|
+
Give Ruby enum-like powers.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem "flexible_enum", git: 'git@github.com:meyouhealth/flexible_enum.git'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install flexible_enum
|
18
|
+
|
19
|
+
## Basic Usage
|
20
|
+
|
21
|
+
The `flexible_enum` class method is mixed into ActiveRecord::Base. Call it to add enum-like powers to any number of existing attributes on a target class.
|
22
|
+
You must provide the name of the attribute and a list of available options. Options consist of a name, value, and optional hash of configuration parameters.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class User < ActiveRecord::Base
|
26
|
+
flexible_enum :status do
|
27
|
+
active 0
|
28
|
+
disabled 1
|
29
|
+
pending 2
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Option values may be any type.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class Product < ActiveRecord::Base
|
38
|
+
flexible_enum :manufacturer do
|
39
|
+
honeywell "HON"
|
40
|
+
sharp "SHCAY"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
## Working with Values
|
46
|
+
|
47
|
+
Available options for each attribute are defined as constants on the target class. The classes above would have defined:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
User::ACTIVE # => 0
|
51
|
+
User::DISABLED # => 1
|
52
|
+
User::PENDING # => 2
|
53
|
+
Product::HONEYWELL # => "HON"
|
54
|
+
Product::SHARP # => "SHCAY"
|
55
|
+
```
|
56
|
+
|
57
|
+
## Setter Methods
|
58
|
+
|
59
|
+
FlexibleEnum adds convenience methods for changing the current value of an attribute and immediately saving it to the database. By default, bang methods are added for each option:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
u = User.new
|
63
|
+
u.active! # Calls update_attributes(status: 0)
|
64
|
+
u.disabled! # Calls update_attributes(status: 1)
|
65
|
+
```
|
66
|
+
|
67
|
+
The name of the setter method can be changed using option configuration parameters:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
class Post < ActiveRecord::Base
|
71
|
+
flexible_enum :visibility do
|
72
|
+
invisible 0, setter: :hide!
|
73
|
+
visible 1, setter: :show!
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
p = Post.new
|
78
|
+
p.show! # Calls update_attributes(visibility: 1)
|
79
|
+
p.hide! # Calls update_attributes(visibility: 0)
|
80
|
+
```
|
81
|
+
|
82
|
+
### Timestamps
|
83
|
+
|
84
|
+
If the target class defines a date and/or time attribute corresponding to the flexible enum option being set it will be updated with the current date/time when using setter methods. For example, Post#show! above will set `visibility = 1`, `visibile_at = Time.now.utc`, and `visible_on = Time.now.utc.to_date` if those columns exist. The existance of columns is checked using ActiveRecord's `attribute_method?` method.
|
85
|
+
|
86
|
+
Use the `:timestamp_attribute` option configuration parameter to change the columns used:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
flexible_enum :status do
|
90
|
+
unknown 0
|
91
|
+
active 1, timestamp_attribute: :actived
|
92
|
+
disabled 2, timestamp_attribute: :disabled
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
Calling `active!` will now attempt to set `actived_at` and `actived_on`.
|
97
|
+
|
98
|
+
## Predicate Methods
|
99
|
+
|
100
|
+
FlexibleEnum adds convenience methods for checking whether an option's value is also the attribute's current value.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
p = Post.new
|
104
|
+
p.show!
|
105
|
+
p.visible? # => true
|
106
|
+
p.invisible? # => false
|
107
|
+
```
|
108
|
+
|
109
|
+
Inverse predicate methods can be added by setting the :inverse configuration parameter. Inverse predicate methods have the reverse logic:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
class Car < ActiveRecord::Base
|
113
|
+
flexible_enum :fuel_type do
|
114
|
+
gasoline 0
|
115
|
+
diesel 1
|
116
|
+
electric 2, inverse: :carbon_emitter
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
c = Car.new
|
121
|
+
c.gasoline!
|
122
|
+
c.carbon_emitter? # => true
|
123
|
+
c.diesel!
|
124
|
+
c.carbon_emitter? # => true
|
125
|
+
c.electric!
|
126
|
+
c.carbon_emitter? # => false
|
127
|
+
```
|
128
|
+
|
129
|
+
## Humanized Values
|
130
|
+
|
131
|
+
Humanized versions of attributes are available. This is convenient for displaying the current value on screen (see "Option Reflection" for rendering drop down lists).
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
c = Car.new(fuel_type: Car::DIESEL)
|
135
|
+
c.human_fuel_type = "Diesel"
|
136
|
+
Car.human_fuel_type(0) # => "Gasoline"
|
137
|
+
Car.fuel_types.collect(&:human_name) # => ["Gasoline", "Diesel", "Electric"]
|
138
|
+
```
|
139
|
+
|
140
|
+
If the flexible enum value is `nil`, the humanized name will also be `nil`:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
c = Car.new(fuel_type: nil)
|
144
|
+
c.human_fuel_type # => nil
|
145
|
+
```
|
146
|
+
|
147
|
+
## Name Method
|
148
|
+
|
149
|
+
The name of the attribute value is available. This allows you to grab the stringified version of the name of the value.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
c = Car.new(fuel_type: Car::CARBON_EMITTER)
|
153
|
+
c.fuel_type_name # => "carbon_emitter"
|
154
|
+
```
|
155
|
+
|
156
|
+
If the flexible enum value is `nil`, the name will also be `nil`:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
c = Car.new(fuel_type: nil)
|
160
|
+
c.fuel_type_name # => nil
|
161
|
+
```
|
162
|
+
|
163
|
+
## Namespaced Attributes
|
164
|
+
|
165
|
+
FlexibleEnum attributes may be namespaced. Adding the namespace option to `flexible_enum` results in constants being defined in a new module.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
class CashRegister < ActiveRecord::Base
|
169
|
+
flexible_enum :drawer_position, namespace: "DrawerPositions" do
|
170
|
+
opened 0
|
171
|
+
closed 1
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# Constants are defined in a new module
|
176
|
+
CashRegister::DrawerPositions::OPENED # => 0
|
177
|
+
CashRegister::DrawerPositions::CLOSED # => 1
|
178
|
+
|
179
|
+
# Convenience methods are not affected by namespace
|
180
|
+
r = CashRegister.new
|
181
|
+
r.opened!
|
182
|
+
r.closed!
|
183
|
+
```
|
184
|
+
|
185
|
+
## Scopes
|
186
|
+
|
187
|
+
FlexibleEnum adds ActiveRecord scopes for each attribute option:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
User.active # => User.where(status: 0)
|
191
|
+
User.disabled # => User.where(status: 1)
|
192
|
+
User.pending # => User.where(status: 2)
|
193
|
+
```
|
194
|
+
|
195
|
+
When an attribute is namespaced a prefix is added to scope names. The prefix is the singularized namespace name (using Active Support):
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
CashRegister.drawer_position_opened # => CashRegister.where(drawer_position: 0)
|
199
|
+
CashRegister.drawer_position_closed # => CashRegister.where(drawer_position: 1)
|
200
|
+
```
|
201
|
+
|
202
|
+
## Custom Options
|
203
|
+
|
204
|
+
Configuration parameters passed to attribute options are saved even if they are unknown. Getting at custom configuration parameters is a little clumsy at the moment but this can still be useful in some cases:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
class EmailEvent < ActiveRecord::Base
|
208
|
+
flexible_enum :event_type do
|
209
|
+
bounce 1, processor_class: RejectedProcessor
|
210
|
+
dropped 2, processor_class: RejectedProcessor
|
211
|
+
opened 3, processor_class: EmailOpenedProcessor
|
212
|
+
delivered 4, processor_class: DeliveryProcessor
|
213
|
+
end
|
214
|
+
|
215
|
+
def process
|
216
|
+
class.event_types[event_type][:processor_class].new(self).process
|
217
|
+
end
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
## Option Introspection
|
222
|
+
|
223
|
+
You may introspect on available options and their configuration parameters:
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
ary = EmailEvent.event_types
|
227
|
+
ary.collect(&:name) # => ["bounce", "dropped", "opened", "delivered"]
|
228
|
+
ary.collect(&:human_name) # => ["Bounce", "Dropped", "Opened", "Delivered"]
|
229
|
+
ary.collect(&:value) # => [1, 2, 3, 4]
|
230
|
+
```
|
231
|
+
|
232
|
+
This works particularly well with ActionView:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
f.collection_select(:event_type, EmailEvent.event_types, :value, :human_name)
|
236
|
+
```
|
237
|
+
|
238
|
+
## Enum Introspection
|
239
|
+
|
240
|
+
You may retrieve a list of all defined `flexible_enum`s on a particular class:
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
class Car < ActiveRecord::Base
|
244
|
+
flexible_enum :status do
|
245
|
+
new 1
|
246
|
+
used 2
|
247
|
+
end
|
248
|
+
|
249
|
+
flexible_enum :car_type do
|
250
|
+
gas 1
|
251
|
+
hybrid 2
|
252
|
+
electric 3
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
Car.flexible_enums # => { status: Car.statuses, car_type: Car.car_types }
|
257
|
+
```
|
258
|
+
|
259
|
+
## Overriding Methods
|
260
|
+
|
261
|
+
You may override any method defined on the target class by FlexibleEnum. In version 0.0.1, `super` behaved as it would without FlexibleEnum being present, you could not call a FlexibleEnum method implementation from an overriding method. As of version 0.0.2, `super` instead references the FlexibleEnum implementation of a method when overriding a FlexibleEnum-defined method.
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
class Item < ActiveRecord::Base
|
265
|
+
flexible_enum :availability do
|
266
|
+
discontinued 0
|
267
|
+
backorder 1
|
268
|
+
in_stock 2
|
269
|
+
end
|
270
|
+
|
271
|
+
# Version 0.0.1
|
272
|
+
# Calling super would throw NoMethodError so we'd have to reimplement the method.
|
273
|
+
def in_stock!
|
274
|
+
BackInStockNotifier.new(self).queue if backorder?
|
275
|
+
update_attribute!(status: IN_STOCK)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Version 0.0.2
|
279
|
+
# Calling super works and is preferred.
|
280
|
+
def in_stock!
|
281
|
+
BackInStockNotifier.new(self).queue if backorder?
|
282
|
+
super
|
283
|
+
end
|
284
|
+
end
|
285
|
+
```
|
286
|
+
|
287
|
+
## Contributing
|
288
|
+
|
289
|
+
Please see [CONTRIBUTING.md].
|
290
|
+
|
291
|
+
## About MeYou Health
|
292
|
+
|
293
|
+

|
294
|
+
|
295
|
+
FlexibleEnum is maintained by MeYou Health, LLC.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'flexible_enum/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "flexible_enum"
|
8
|
+
spec.version = FlexibleEnum::VERSION
|
9
|
+
|
10
|
+
contributors = `git shortlog -sne`.split("\n").collect { |l| l.scan(/\t(.*) <(.*)>/) }.flatten(1)
|
11
|
+
spec.authors = contributors.collect(&:first)
|
12
|
+
spec.email = contributors.collect(&:last)
|
13
|
+
|
14
|
+
spec.description = %q{Helpers for enum-like fields}
|
15
|
+
spec.summary = %q{Helpers for enum-like fields}
|
16
|
+
spec.homepage = "https://github.com/meyouhealth/flexible_enum"
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "activesupport", ">= 3.0"
|
25
|
+
|
26
|
+
spec.add_development_dependency "appraisal"
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency "fury"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "sqlite3"
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class AbstractConfigurator < Struct.new(:feature_module, :attribute_name, :module_for_elements, :elements)
|
3
|
+
def add_class_method(method_name, &block)
|
4
|
+
feature_module.const_get(:ClassMethods).send(:define_method, method_name, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_instance_method(method_name, &block)
|
8
|
+
feature_module.send(:define_method, method_name, &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class Configuration
|
3
|
+
def self.load(&block)
|
4
|
+
new.tap {|i| i.instance_eval(&block) }
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@config = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def elements
|
12
|
+
@config.dup
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(element_name, value, options = {})
|
16
|
+
@config[element_name] = options
|
17
|
+
@config[element_name][:value] = value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class ConstantConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
elements.each do |element_name, element_config|
|
5
|
+
constant_name = element_name.to_s.upcase
|
6
|
+
constant_value = element_config[:value]
|
7
|
+
module_for_elements.const_set(constant_name, constant_value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
module FlexibleEnum
|
5
|
+
module Mixin
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def flexible_enums
|
10
|
+
@flexible_enums ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def flexible_enum(attribute_name, attribute_options = {}, &config)
|
14
|
+
# Methods are defined on the feature module which in turn is mixed in to the target class
|
15
|
+
feature_module = Module.new do |m|
|
16
|
+
extend ActiveSupport::Concern
|
17
|
+
const_set :ClassMethods, Module.new
|
18
|
+
def m.inspect
|
19
|
+
"FlexibleEnum(#{self})"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# The module that will hold references to value constants
|
24
|
+
module_for_elements = attribute_options[:namespace] ? self.const_set(attribute_options[:namespace], Module.new) : feature_module
|
25
|
+
|
26
|
+
# Read configuration
|
27
|
+
elements = Configuration.load(&config).elements
|
28
|
+
|
29
|
+
# Configure the target object for the given attribute
|
30
|
+
configurators = [ConstantConfigurator,
|
31
|
+
NameConfigurator,
|
32
|
+
QuestionMethodConfigurator,
|
33
|
+
SetterMethodConfigurator,
|
34
|
+
ScopeConfigurator,
|
35
|
+
PotentialValuesConfigurator]
|
36
|
+
configurators.each do |configurator|
|
37
|
+
configurator.new(feature_module, attribute_name, module_for_elements, elements).apply
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add functionality to target inheritance chain
|
41
|
+
send(:include, feature_module)
|
42
|
+
|
43
|
+
flexible_enums[attribute_name] = public_send("#{attribute_name.to_s.pluralize}_by_sym")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class NameConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
configurator = self
|
5
|
+
|
6
|
+
add_instance_method("#{attribute_name}_name") do
|
7
|
+
value = send(configurator.attribute_name)
|
8
|
+
configurator.name_for(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
add_class_method("human_#{attribute_name}") do |value|
|
12
|
+
configurator.human_name_for(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
add_instance_method("human_#{attribute_name}") do
|
16
|
+
value = send(configurator.attribute_name)
|
17
|
+
configurator.human_name_for(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def name_for(value)
|
22
|
+
if value
|
23
|
+
element_info(value).first.to_s
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def human_name_for(value)
|
30
|
+
if value
|
31
|
+
element_name, element_config = element_info(value)
|
32
|
+
element_config[:human_name] || element_name.to_s.humanize
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def element_info(value)
|
41
|
+
elements.select{|e,c| c[:value] == value }.first
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class PotentialValuesConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
configurator = self
|
5
|
+
|
6
|
+
add_class_method(attribute_name.to_s.pluralize) do
|
7
|
+
configurator.elements.map(&configurator.option_builder_for_target(self)).sort_by(&:value)
|
8
|
+
end
|
9
|
+
|
10
|
+
add_class_method("#{attribute_name.to_s.pluralize}_by_sym") do
|
11
|
+
configurator.elements.inject({}) do |all_options, (element_name, element_config)|
|
12
|
+
all_options.merge element_name => configurator.option_builder_for_target(self).call(element_name, element_config)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
add_class_method("#{attribute_name}_value_for") do |sym_string_or_const|
|
17
|
+
element_by_symbol = send(:"#{configurator.attribute_name.to_s.pluralize}_by_sym")[:"#{sym_string_or_const.to_s.downcase}"]
|
18
|
+
element_by_value = send(configurator.attribute_name.to_s.pluralize).select { |e| e.value == sym_string_or_const }.first
|
19
|
+
(element_by_symbol || element_by_value).try(:value) or raise("Unknown enumeration element: #{sym_string_or_const}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def option_builder_for_target(target_instance)
|
24
|
+
proc { |element_name, element_config| Option.new(target_instance, attribute_name, element_name, element_config) }
|
25
|
+
end
|
26
|
+
|
27
|
+
class Option < Struct.new(:target_class, :attribute_name, :element_name, :element_config)
|
28
|
+
def name
|
29
|
+
element_name.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
def human_name
|
33
|
+
target_class.send("human_#{attribute_name}", value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def value
|
37
|
+
element_config[:value]
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
element_config[key]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class QuestionMethodConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
elements.each do |element_name, element_config|
|
5
|
+
attribute_name = self.attribute_name
|
6
|
+
|
7
|
+
# Define question method
|
8
|
+
add_instance_method("#{element_name}?") do
|
9
|
+
self.send(attribute_name) == element_config[:value]
|
10
|
+
end
|
11
|
+
|
12
|
+
# Define inverse question method (if requested)
|
13
|
+
if element_config[:inverse]
|
14
|
+
add_instance_method("#{element_config[:inverse]}?") do
|
15
|
+
!self.send("#{element_name}?")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class ScopeConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
configurator = self
|
5
|
+
|
6
|
+
elements.each do |element_name, element_config|
|
7
|
+
add_class_method(scope_name(element_name)) do
|
8
|
+
unscope(:where => configurator.attribute_name).where(configurator.attribute_name => element_config[:value])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def scope_name(option)
|
16
|
+
if feature_module == module_for_elements
|
17
|
+
option
|
18
|
+
else
|
19
|
+
"#{module_for_elements.to_s.split('::').last.underscore.singularize}_#{option}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module FlexibleEnum
|
2
|
+
class SetterMethodConfigurator < AbstractConfigurator
|
3
|
+
def apply
|
4
|
+
attribute_name = self.attribute_name
|
5
|
+
|
6
|
+
elements.each do |element_name, element_config|
|
7
|
+
bang_method_name = element_config[:setter] || "#{element_name}!"
|
8
|
+
attributes = {attribute_name => element_config[:value]}
|
9
|
+
timestamp_attribute_name = element_config[:timestamp_attribute] || element_name
|
10
|
+
|
11
|
+
add_instance_method(bang_method_name) do
|
12
|
+
time = Time.now.utc
|
13
|
+
attributes["#{timestamp_attribute_name}_on".to_sym] = time.to_date if self.class.attribute_method?("#{timestamp_attribute_name}_on")
|
14
|
+
attributes["#{timestamp_attribute_name}_at".to_sym] = time if self.class.attribute_method?("#{timestamp_attribute_name}_at")
|
15
|
+
update_attributes(attributes)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'active_support/lazy_load_hooks'
|
2
|
+
require 'active_support/core_ext/object'
|
3
|
+
|
4
|
+
module FlexibleEnum
|
5
|
+
autoload :Mixin, 'flexible_enum/mixin'
|
6
|
+
autoload :Configuration, 'flexible_enum/configuration'
|
7
|
+
autoload :AbstractConfigurator, 'flexible_enum/abstract_configurator'
|
8
|
+
autoload :ConstantConfigurator, 'flexible_enum/constant_configurator'
|
9
|
+
autoload :NameConfigurator, 'flexible_enum/name_configurator'
|
10
|
+
autoload :QuestionMethodConfigurator, 'flexible_enum/question_method_configurator'
|
11
|
+
autoload :SetterMethodConfigurator, 'flexible_enum/setter_method_configurator'
|
12
|
+
autoload :ScopeConfigurator, 'flexible_enum/scope_configurator'
|
13
|
+
autoload :PotentialValuesConfigurator, 'flexible_enum/potential_values_configurator'
|
14
|
+
autoload :Version, 'flexible_enum/version'
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveSupport.on_load :active_record do
|
18
|
+
include FlexibleEnum::Mixin
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "constant definition" do
|
4
|
+
it "sets constants for each value choice" do
|
5
|
+
expect(CashRegister::UNKNOWN).to eq(0)
|
6
|
+
expect(CashRegister::NOT_ACTIVE).to eq(10)
|
7
|
+
expect(CashRegister::ACTIVE).to eq(20)
|
8
|
+
expect(CashRegister::HONEYWELL).to eq("HON")
|
9
|
+
expect(CashRegister::SHARP).to eq("SHCAY")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "sets constants for each namespaced attribute value choice" do
|
13
|
+
expect(CashRegister::DrawerPositions::OPENED).to eq(0)
|
14
|
+
expect(CashRegister::DrawerPositions::CLOSED).to eq(1)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "target class exposing flexible_enums" do
|
4
|
+
it "allows consumers to find all defined flexible_enums" do
|
5
|
+
expect(CashRegister.flexible_enums[:status].keys).to eq([:unknown, :not_active, :active, :alarm, :full, :empty])
|
6
|
+
expect(CashRegister.flexible_enums[:drawer_position].keys).to eq([:opened, :closed])
|
7
|
+
expect(CashRegister.flexible_enums[:manufacturer].keys).to eq([:honeywell, :sharp])
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "inheritance in target class" do
|
4
|
+
it "allows calling super from overwritten methods" do
|
5
|
+
register = CashRegister.new
|
6
|
+
register.honeywell!
|
7
|
+
|
8
|
+
def register.sharp!
|
9
|
+
before = manufacturer
|
10
|
+
super
|
11
|
+
[before, manufacturer]
|
12
|
+
end
|
13
|
+
|
14
|
+
expect(register.sharp!).to eq(["HON", "SHCAY"])
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "name values" do
|
4
|
+
it "retrieves the name for the current value" do
|
5
|
+
register = CashRegister.new
|
6
|
+
register.status = CashRegister::UNKNOWN
|
7
|
+
expect(register.status_name).to eq("unknown")
|
8
|
+
register.status = CashRegister::NOT_ACTIVE
|
9
|
+
expect(register.status_name).to eq("not_active")
|
10
|
+
register.status = nil
|
11
|
+
expect(register.status_name).to be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "retrieves the human name of the current value" do
|
15
|
+
register = CashRegister.new
|
16
|
+
register.status = CashRegister::UNKNOWN
|
17
|
+
expect(register.human_status).to eq("Unknown")
|
18
|
+
register.status = CashRegister::NOT_ACTIVE
|
19
|
+
expect(register.human_status).to eq("Not active")
|
20
|
+
register.status = nil
|
21
|
+
expect(register.human_status).to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "retrieves human names for available options" do
|
25
|
+
expect(CashRegister.human_status(CashRegister::UNKNOWN)).to eq("Unknown")
|
26
|
+
expect(CashRegister.human_status(CashRegister::NOT_ACTIVE)).to eq("Not active")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "retrieves custom human names when provided" do
|
30
|
+
expect(CashRegister.human_status(CashRegister::ALARM)).to eq("Help I'm being robbed!")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "retrieves the human name of the current value of namespaced attributes" do
|
34
|
+
opened_register = CashRegister.new.tap {|r| r.drawer_position = CashRegister::DrawerPositions::OPENED }
|
35
|
+
closed_register = CashRegister.new.tap {|r| r.drawer_position = CashRegister::DrawerPositions::CLOSED }
|
36
|
+
expect(opened_register.human_drawer_position).to eq("Opened")
|
37
|
+
expect(closed_register.human_drawer_position).to eq("Closed")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "retrieves human names for known constants of namespaced attributes" do
|
41
|
+
expect(CashRegister.human_drawer_position(CashRegister::DrawerPositions::OPENED)).to eq("Opened")
|
42
|
+
expect(CashRegister.human_drawer_position(CashRegister::DrawerPositions::CLOSED)).to eq("Closed")
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "reflection of attribute options" do
|
4
|
+
it "returns a list of possible elements" do
|
5
|
+
expect(CashRegister.drawer_positions.collect(&:name)).to eq(["opened", "closed"])
|
6
|
+
expect(CashRegister.drawer_positions.collect(&:human_name)).to eq(["Opened", "Closed"])
|
7
|
+
expect(CashRegister.drawer_positions.collect(&:value)).to eq([0, 1])
|
8
|
+
end
|
9
|
+
|
10
|
+
it "finds the element metadata for the option provided by symbol" do
|
11
|
+
opened = CashRegister.drawer_positions_by_sym[:opened]
|
12
|
+
expect(opened.name).to eq("opened")
|
13
|
+
expect(opened.human_name).to eq("Opened")
|
14
|
+
expect(opened.value).to eq(0)
|
15
|
+
|
16
|
+
closed = CashRegister.drawer_positions_by_sym[:closed]
|
17
|
+
expect(closed.name).to eq("closed")
|
18
|
+
expect(closed.human_name).to eq("Closed")
|
19
|
+
expect(closed.value).to eq(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "finds the value corresponding to the option provided by its value" do
|
23
|
+
expect(CashRegister.status_value_for(CashRegister::ACTIVE)).to eq(CashRegister::ACTIVE)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "finds the value corresponding to the option name provided as a string" do
|
27
|
+
expect(CashRegister.status_value_for("active")).to eq(CashRegister::ACTIVE)
|
28
|
+
expect(CashRegister.status_value_for("ACTIVE")).to eq(CashRegister::ACTIVE)
|
29
|
+
expect(CashRegister.manufacturer_value_for("honeywell")).to eq("HON")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "finds the value for a given option name provided as a symbol" do
|
33
|
+
expect(CashRegister.status_value_for(:active)).to eq(CashRegister::ACTIVE)
|
34
|
+
expect(CashRegister.drawer_position_value_for(:opened)).to eq(CashRegister::DrawerPositions::OPENED)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises an exception for invalid options" do
|
38
|
+
expect { CashRegister.status_value_for(666) }.to raise_error("Unknown enumeration element: 666")
|
39
|
+
expect { CashRegister.status_value_for("bad_string") }.to raise_error("Unknown enumeration element: bad_string")
|
40
|
+
expect { CashRegister.status_value_for(:bad_symbol) }.to raise_error("Unknown enumeration element: bad_symbol")
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "default behavior of flexible_enum" do
|
4
|
+
it "adds default predicates that indicate the current value" do
|
5
|
+
register = CashRegister.new
|
6
|
+
register.status = CashRegister::ACTIVE
|
7
|
+
expect(register).to_not be_unknown
|
8
|
+
expect(register).to_not be_not_active
|
9
|
+
expect(register).to be_active
|
10
|
+
end
|
11
|
+
|
12
|
+
it "adds predicates that indicate the negation of the current value" do
|
13
|
+
register = CashRegister.new
|
14
|
+
register.status = CashRegister::UNKNOWN
|
15
|
+
expect(register).to be_unknown
|
16
|
+
expect(register).to_not be_known
|
17
|
+
register.status = CashRegister::NOT_ACTIVE
|
18
|
+
expect(register).to_not be_unknown
|
19
|
+
expect(register).to be_known
|
20
|
+
end
|
21
|
+
|
22
|
+
it "does not set a default value" do
|
23
|
+
default = CashRegister.new
|
24
|
+
expect(default.status).to be_nil
|
25
|
+
expect(default).to_not be_unknown
|
26
|
+
expect(default).to_not be_not_active
|
27
|
+
expect(default).to_not be_active
|
28
|
+
end
|
29
|
+
|
30
|
+
it "adds predicates that indicate the current value when namespaced" do
|
31
|
+
register = CashRegister.new
|
32
|
+
register.drawer_position = CashRegister::DrawerPositions::OPENED
|
33
|
+
expect(register).to be_opened
|
34
|
+
expect(register).to_not be_closed
|
35
|
+
register.drawer_position = CashRegister::DrawerPositions::CLOSED
|
36
|
+
expect(register).to_not be_opened
|
37
|
+
expect(register).to be_closed
|
38
|
+
end
|
39
|
+
end
|
data/spec/scopes_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "scopes" do
|
4
|
+
it "builds scopes for each element" do
|
5
|
+
actives = CashRegister.create!(status: CashRegister::ACTIVE)
|
6
|
+
alarms = CashRegister.create!(status: CashRegister::ALARM)
|
7
|
+
|
8
|
+
expect(CashRegister.active).to contain_exactly(actives)
|
9
|
+
expect(CashRegister.alarm).to contain_exactly(alarms)
|
10
|
+
expect(CashRegister.unknown).to be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it "builds scopes with prefixed names for each namespaced element" do
|
14
|
+
opened = CashRegister.new.tap(&:open!)
|
15
|
+
closed = CashRegister.new.tap(&:close!)
|
16
|
+
|
17
|
+
expect(CashRegister.drawer_position_opened).to contain_exactly(opened)
|
18
|
+
expect(CashRegister.drawer_position_closed).to contain_exactly(closed)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "builds scopes that aren't affected by default scopes" do
|
22
|
+
WithDefaultScope.new.tap(&:active!)
|
23
|
+
passive = WithDefaultScope.new.tap(&:passive!)
|
24
|
+
|
25
|
+
expect(WithDefaultScope.passive).to contain_exactly(passive)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "setter methods" do
|
4
|
+
subject(:register) { CashRegister.new }
|
5
|
+
|
6
|
+
it "adds default bang methods for setting a new value" do
|
7
|
+
expect(register.status).to be_nil
|
8
|
+
register.active!
|
9
|
+
expect(register.status).to eq(20)
|
10
|
+
register.not_active!
|
11
|
+
expect(register.status).to eq(10)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "adds custom bang methods for setting a new value" do
|
15
|
+
expect(register.drawer_position).to be_nil
|
16
|
+
register.open!
|
17
|
+
expect(register.drawer_position).to eq(0)
|
18
|
+
register.close!
|
19
|
+
expect(register.drawer_position).to eq(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "updating database" do
|
23
|
+
let!(:now) { Time.now }
|
24
|
+
let(:updates) { [] }
|
25
|
+
|
26
|
+
before { allow(Time).to receive(:now).and_return(now) }
|
27
|
+
|
28
|
+
it "immediately dispatches a validation-free update" do
|
29
|
+
register.active!
|
30
|
+
register.close!
|
31
|
+
|
32
|
+
expect(register).to be_active
|
33
|
+
expect(register).to be_closed
|
34
|
+
end
|
35
|
+
|
36
|
+
it "updates default timestamp columns with the current date and time" do
|
37
|
+
register.fill!
|
38
|
+
expect(register).to be_full
|
39
|
+
expect(register.full_at).to eq(now)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "updates custom timestamp columns with the current date and time" do
|
43
|
+
register.empty!
|
44
|
+
expect(register).to be_empty
|
45
|
+
expect(register.emptied_at).to eq(now)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'flexible_enum'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.around(:each) do |example|
|
8
|
+
ActiveRecord::Base.transaction do
|
9
|
+
example.run
|
10
|
+
raise ActiveRecord::Rollback
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Schema.define do
|
16
|
+
create_table "cash_registers" do |t|
|
17
|
+
t.integer "status"
|
18
|
+
t.datetime "emptied_at"
|
19
|
+
t.datetime "emptied_on"
|
20
|
+
t.datetime "full_at"
|
21
|
+
t.string "manufacturer"
|
22
|
+
t.integer "drawer_position"
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table "with_default_scopes" do |t|
|
26
|
+
t.integer "status"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class CashRegister < ActiveRecord::Base
|
31
|
+
flexible_enum :status do
|
32
|
+
unknown 0, inverse: :known
|
33
|
+
not_active 10, my_custom_option: "Nothing to see here"
|
34
|
+
active 20
|
35
|
+
alarm 21, human_name: "Help I'm being robbed!"
|
36
|
+
full 22, setter: :fill!
|
37
|
+
empty 23, timestamp_attribute: :emptied
|
38
|
+
end
|
39
|
+
|
40
|
+
flexible_enum :drawer_position, :namespace => "DrawerPositions" do
|
41
|
+
opened 0, setter: :open!
|
42
|
+
closed 1, setter: :close!
|
43
|
+
end
|
44
|
+
|
45
|
+
flexible_enum :manufacturer do
|
46
|
+
honeywell "HON"
|
47
|
+
sharp "SHCAY"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class WithDefaultScope < ActiveRecord::Base
|
52
|
+
flexible_enum :status do
|
53
|
+
active 0
|
54
|
+
passive 1
|
55
|
+
end
|
56
|
+
|
57
|
+
default_scope { where(status: ACTIVE) }
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flexible_enum
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Daubert
|
8
|
+
- Alex Robbin
|
9
|
+
- Adam Prescott
|
10
|
+
- Matthew Daubert
|
11
|
+
- Chad Dressler
|
12
|
+
- Sean Santry
|
13
|
+
- Adam Prescott
|
14
|
+
- Sean Santry
|
15
|
+
- jon.zeppieri
|
16
|
+
- Alex Robbin
|
17
|
+
- David C. Goldhirsch
|
18
|
+
- David Larrabee
|
19
|
+
- Guillermo Guerini
|
20
|
+
- Matthew Daubert
|
21
|
+
autorequire:
|
22
|
+
bindir: bin
|
23
|
+
cert_chain: []
|
24
|
+
date: 2015-05-06 00:00:00.000000000 Z
|
25
|
+
dependencies:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activesupport
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: appraisal
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: bundler
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.3'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.3'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: fury
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rake
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rspec
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: sqlite3
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
type: :development
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
description: Helpers for enum-like fields
|
125
|
+
email:
|
126
|
+
- matt.daubert@meyouhealth.com
|
127
|
+
- alex.robbin@meyouhealth.com
|
128
|
+
- adam@aprescott.com
|
129
|
+
- mdaubert@gmail.com
|
130
|
+
- chad@dresslerfamily.com
|
131
|
+
- sean.santry@meyouhealth.com
|
132
|
+
- adam.prescott@meyouhealth.com
|
133
|
+
- sean@seansantry.com
|
134
|
+
- jon.zeppieri@meyouhealth.com
|
135
|
+
- alex@robbinsweb.biz
|
136
|
+
- dgoldhirsch@yahoo.com
|
137
|
+
- david.larrabee@meyouhealth.com
|
138
|
+
- guillermo@gguerini.com
|
139
|
+
- mdaubert+github@gmail.com
|
140
|
+
executables: []
|
141
|
+
extensions: []
|
142
|
+
extra_rdoc_files: []
|
143
|
+
files:
|
144
|
+
- .gitignore
|
145
|
+
- .travis.yml
|
146
|
+
- Appraisals
|
147
|
+
- CONTRIBUTING.md
|
148
|
+
- Gemfile
|
149
|
+
- LICENSE.txt
|
150
|
+
- README.md
|
151
|
+
- Rakefile
|
152
|
+
- flexible_enum.gemspec
|
153
|
+
- gemfiles/rails_4.1.gemfile
|
154
|
+
- gemfiles/rails_4.2.gemfile
|
155
|
+
- lib/flexible_enum.rb
|
156
|
+
- lib/flexible_enum/abstract_configurator.rb
|
157
|
+
- lib/flexible_enum/configuration.rb
|
158
|
+
- lib/flexible_enum/constant_configurator.rb
|
159
|
+
- lib/flexible_enum/mixin.rb
|
160
|
+
- lib/flexible_enum/name_configurator.rb
|
161
|
+
- lib/flexible_enum/potential_values_configurator.rb
|
162
|
+
- lib/flexible_enum/question_method_configurator.rb
|
163
|
+
- lib/flexible_enum/scope_configurator.rb
|
164
|
+
- lib/flexible_enum/setter_method_configurator.rb
|
165
|
+
- lib/flexible_enum/version.rb
|
166
|
+
- spec/constant_definition_spec.rb
|
167
|
+
- spec/custom_options_spec.rb
|
168
|
+
- spec/enum_introspection_spec.rb
|
169
|
+
- spec/inheritance_spec.rb
|
170
|
+
- spec/name_values_spec.rb
|
171
|
+
- spec/potential_values_spec.rb
|
172
|
+
- spec/predicate_methods_spec.rb
|
173
|
+
- spec/scopes_spec.rb
|
174
|
+
- spec/setter_methods_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
homepage: https://github.com/meyouhealth/flexible_enum
|
177
|
+
licenses:
|
178
|
+
- MIT
|
179
|
+
metadata: {}
|
180
|
+
post_install_message:
|
181
|
+
rdoc_options: []
|
182
|
+
require_paths:
|
183
|
+
- lib
|
184
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - '>='
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '0'
|
189
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - '>='
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '0'
|
194
|
+
requirements: []
|
195
|
+
rubyforge_project:
|
196
|
+
rubygems_version: 2.0.14
|
197
|
+
signing_key:
|
198
|
+
specification_version: 4
|
199
|
+
summary: Helpers for enum-like fields
|
200
|
+
test_files:
|
201
|
+
- spec/constant_definition_spec.rb
|
202
|
+
- spec/custom_options_spec.rb
|
203
|
+
- spec/enum_introspection_spec.rb
|
204
|
+
- spec/inheritance_spec.rb
|
205
|
+
- spec/name_values_spec.rb
|
206
|
+
- spec/potential_values_spec.rb
|
207
|
+
- spec/predicate_methods_spec.rb
|
208
|
+
- spec/scopes_spec.rb
|
209
|
+
- spec/setter_methods_spec.rb
|
210
|
+
- spec/spec_helper.rb
|