flexible_enum 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![http://meyouhealth.com/](https://avatars3.githubusercontent.com/u/249181?v=3&s=200)
|
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
|