power_enum 0.3.0 → 0.3.1
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.
- data/LICENSE +4 -1
- data/README.md +103 -72
- data/lib/power_enum/schema/schema_statements.rb +12 -4
- metadata +10 -10
data/LICENSE
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
Copyright (c) 2005 Trevor Squires
|
1
|
+
Initial Version Copyright (c) 2005 Trevor Squires
|
2
|
+
Rails 3 Updates Copyright (c) 2010 Pivotal Labs
|
3
|
+
Initial Test Suite Copyright (c) 2011 Sergey Potapov
|
4
|
+
Subsequent Updates Copyright (c) 2011 Arthur Shagall
|
2
5
|
|
3
6
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
7
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -9,8 +9,8 @@ It allows you to cleanly solve many of the problems that the traditional Rails a
|
|
9
9
|
It is particularly suitable for scenarios where your Rails application is not the only user of the database, such as
|
10
10
|
when it's used for analytics or reporting.
|
11
11
|
|
12
|
-
Power Enum is built on top of the Rails 3 modernization made by the fine folks at Protocool https://github.com/protocool/
|
13
|
-
to the original plugin by Trevor Squires located at https://github.com/protocool/
|
12
|
+
Power Enum is built on top of the Rails 3 modernization made by the fine folks at Protocool https://github.com/protocool/enumerations\_mixin
|
13
|
+
to the original plugin by Trevor Squires located at https://github.com/protocool/enumerations\_mixin. While many of the core ideas remain,
|
14
14
|
it has been reworked and a full test suite written to facilitate further development.
|
15
15
|
|
16
16
|
At it's most basic level, it allows you to say things along the lines of:
|
@@ -39,17 +39,18 @@ then run
|
|
39
39
|
|
40
40
|
This package adds two mixins and a helper to Rails' ActiveRecord, as well as methods to migrations to simplify the creation of backing tables.
|
41
41
|
|
42
|
-
|
43
|
-
At a minimum, the database table for
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
active.
|
42
|
+
`acts_as_enumerated` provides capabilities to treat your model and its records as an enumeration.
|
43
|
+
At a minimum, the database table for an acts\_as\_enumerated must contain an 'id' column and a column
|
44
|
+
to hold the value of the enum ('name' by default). It is strongly recommended that there be
|
45
|
+
a NOT NULL constraint on the 'name' column. All instances for the `acts_as_enumerated` model
|
46
|
+
are cached in memory. If the table has an 'active' column, the value of that attribute
|
47
|
+
will be used to determine which enum instances are active.
|
48
|
+
Otherwise, all values are considered active.
|
48
49
|
|
49
|
-
|
50
|
+
`has_enumerated` adds methods to your ActiveRecord model for setting and retrieving enumerated values using an associated acts\_as\_enumerated model.
|
50
51
|
|
51
|
-
There is also an
|
52
|
-
cluttering up your models directory with
|
52
|
+
There is also an `ActiveRecord::VirtualEnumerations` helper module to create 'virtual' acts\_as\_enumerated models which helps to avoid
|
53
|
+
cluttering up your models directory with acts\_as\_enumerated classes.
|
53
54
|
|
54
55
|
## How to use it
|
55
56
|
|
@@ -61,8 +62,6 @@ In the following example, we'll look at a Booking that can have several types of
|
|
61
62
|
# The above is equivalent to saying
|
62
63
|
# create_table :booking_statuses do |t|
|
63
64
|
# t.string :name, :limit => 50, :null => false
|
64
|
-
|
65
|
-
# t.timestamps
|
66
65
|
# end
|
67
66
|
|
68
67
|
create_table :bookings do |t|
|
@@ -76,23 +75,35 @@ In the following example, we'll look at a Booking that can have several types of
|
|
76
75
|
|
77
76
|
There are two methods added to Rails migrations:
|
78
77
|
|
79
|
-
##### create_enum(enum_name, options = {})
|
78
|
+
##### `create_enum(enum_name, options = {})`
|
80
79
|
|
81
|
-
Creates a new enum table.
|
80
|
+
Creates a new enum table. `enum_name` will be automatically pluralized. The following options are supported:
|
82
81
|
|
83
82
|
- [:name_column] Specify the column name for name of the enum. By default it's :name. This can be a String or a Symbol
|
84
|
-
- [:description] Set this to
|
83
|
+
- [:description] Set this to `true` to have a 'description' column generated.
|
85
84
|
- [:name_limit] Set this define the limit of the name column.
|
86
85
|
- [:desc_limit] Set this to define the limit of the description column
|
87
|
-
- [:active] Set this to
|
86
|
+
- [:active] Set this to `true` to have a boolean 'active' column generated. The 'active' column will have the options of NOT NULL and DEFAULT TRUE.
|
87
|
+
- [:timestamps] Set this to `true` to have the timestamp columns (created\_at and updated\_at) generated
|
88
88
|
|
89
89
|
Example:
|
90
90
|
|
91
|
+
create_enum :booking_status
|
92
|
+
|
93
|
+
is the equivalent of
|
94
|
+
|
95
|
+
create_table :booking_statuses do |t|
|
96
|
+
t.string :name, :null => false
|
97
|
+
end
|
98
|
+
|
99
|
+
In a more complex case:
|
100
|
+
|
91
101
|
create_enum :booking_status, :name_column => :booking_name,
|
92
102
|
:name_limit => 50,
|
93
103
|
:description => true,
|
94
104
|
:desc_limit => 100,
|
95
|
-
:active => true
|
105
|
+
:active => true,
|
106
|
+
:timestamps => true
|
96
107
|
|
97
108
|
is the equivalent of
|
98
109
|
|
@@ -103,9 +114,9 @@ is the equivalent of
|
|
103
114
|
t.timestamps
|
104
115
|
end
|
105
116
|
|
106
|
-
##### remove_enum(enum_name)
|
117
|
+
##### `remove_enum(enum_name)`
|
107
118
|
|
108
|
-
Drops the enum table.
|
119
|
+
Drops the enum table. `enum_name` will be automatically pluralized.
|
109
120
|
|
110
121
|
Example:
|
111
122
|
|
@@ -115,77 +126,85 @@ is the equivalent of
|
|
115
126
|
|
116
127
|
drop_table :booking_statuses
|
117
128
|
|
118
|
-
###
|
129
|
+
### acts\_as\_enumerated
|
119
130
|
|
120
131
|
class BookingStatus < ActiveRecord::Base
|
121
|
-
acts_as_enumerated :conditions
|
122
|
-
|
123
|
-
|
124
|
-
|
132
|
+
acts_as_enumerated :conditions => 'optional_sql_conditions',
|
133
|
+
:order => 'optional_sql_orderby',
|
134
|
+
:on_lookup_failure => :optional_class_method,
|
135
|
+
:name_column => 'optional_name_column' #If required, may override the default name column
|
125
136
|
end
|
126
137
|
|
127
138
|
With that, your BookingStatus class will have the following methods defined:
|
128
139
|
|
129
140
|
#### Class Methods
|
130
141
|
|
131
|
-
##### [](arg)
|
142
|
+
##### `[](arg)`
|
132
143
|
|
133
|
-
|
144
|
+
`BookingStatus[arg]` performs a lookup for the BookingStatus instance for the given arg. The arg value can be a 'string' or a :symbol,
|
145
|
+
in which case the lookup will be against the BookingStatus.name field. Alternatively arg can be a Fixnum,
|
146
|
+
in which case the lookup will be against the BookingStatus.id field.
|
134
147
|
|
135
|
-
The
|
148
|
+
The `:on_lookup_failure` option specifies the name of a *class* method to invoke when the `[]` method is unable to locate a BookingStatus record for arg.
|
149
|
+
The default is the built-in `:enforce_none` which returns nil. There are also built-ins for `:enforce_strict` (raise and exception regardless of the type for arg),
|
150
|
+
`:enforce_strict_literals` (raises an exception if the arg is a Fixnum or Symbol), `:enforce_strict_ids` (raises and exception if the arg is a Fixnum)
|
151
|
+
and `:enforce_strict_symbols` (raises an exception if the arg is a Symbol).
|
136
152
|
|
137
|
-
The purpose of the
|
153
|
+
The purpose of the `:on_lookup_failure` option is that a) under some circumstances a lookup failure is a Bad Thing and action should be taken,
|
154
|
+
therefore b) a fallback action should be easily configurable.
|
138
155
|
|
139
|
-
##### all
|
156
|
+
##### `all`
|
140
157
|
|
141
|
-
|
158
|
+
`BookingStatus.all` returns an array of all BookingStatus records that match the `:conditions` specified in `acts_as_enumerated`, in the order specified by `:order`.
|
142
159
|
|
143
|
-
##### active
|
160
|
+
##### `active`
|
144
161
|
|
145
|
-
|
162
|
+
`BookingStatus.active` returns an array of all BookingStatus records that are marked active. See the `active?` instance method.
|
146
163
|
|
147
|
-
##### inactive
|
164
|
+
##### `inactive`
|
148
165
|
|
149
|
-
|
166
|
+
`BookingStatus.inactive` returns an array of all BookingStatus records that are inactive. See the `inactive?` instance method.
|
150
167
|
|
151
168
|
#### Instance Methods
|
152
169
|
|
153
170
|
Each enumeration model gets the following instance methods.
|
154
171
|
|
155
|
-
#####
|
172
|
+
##### `===(arg)`
|
156
173
|
|
157
|
-
|
174
|
+
`BookingStatus[:foo] === arg` returns true if `BookingStatus[:foo] === BookingStatus[arg]` returns true if arg is Fixnum, String,
|
175
|
+
or Symbol. If arg is an Array, will compare every element of the array and return true if any element return true for `===`.
|
158
176
|
|
159
|
-
You should note that defining an
|
177
|
+
You should note that defining an `:on_lookup_failure` method that raises an exception will cause `===` to also raise an exception for any lookup failure of `BookingStatus[arg]`.
|
160
178
|
|
161
|
-
|
179
|
+
`like?` is aliased to `===`
|
162
180
|
|
163
|
-
##### in?(*list)
|
181
|
+
##### `in?(*list)`
|
164
182
|
|
165
|
-
Returns true if any element in the list returns true for
|
183
|
+
Returns true if any element in the list returns true for `===(arg)`, false otherwise.
|
166
184
|
|
167
|
-
##### name
|
185
|
+
##### `name`
|
168
186
|
|
169
|
-
Returns the 'name' of the enum, i.e. the value in the
|
187
|
+
Returns the 'name' of the enum, i.e. the value in the `:name_column` attribute of the enumeration model.
|
170
188
|
|
171
|
-
##### name_sym
|
189
|
+
##### `name_sym`
|
172
190
|
|
173
|
-
Returns the symbol representation of the name of the enum.
|
191
|
+
Returns the symbol representation of the name of the enum. `BookingStatus[:foo].name_sym` returns :foo.
|
174
192
|
|
175
|
-
##### active
|
193
|
+
##### `active?`
|
176
194
|
|
177
195
|
Returns true if the instance is active, false otherwise. If it has an attribute 'active',
|
178
|
-
returns the attribute cast to a boolean, otherwise returns true. This method is used by the
|
196
|
+
returns the attribute cast to a boolean, otherwise returns true. This method is used by the `active`
|
179
197
|
class method to select active enums.
|
180
198
|
|
181
|
-
##### inactive
|
199
|
+
##### `inactive?`
|
182
200
|
|
183
|
-
Returns true if the instance is inactive, false otherwise. Default implementations returns
|
184
|
-
This method is used by the
|
201
|
+
Returns true if the instance is inactive, false otherwise. Default implementations returns `!active?`
|
202
|
+
This method is used by the `inactive` class method to select inactive enums.
|
185
203
|
|
186
204
|
#### Notes
|
187
205
|
|
188
|
-
acts_as_enumerated records are considered immutable. By default you cannot create/alter/destroy instances because they are cached in memory.
|
206
|
+
`acts_as_enumerated` records are considered immutable. By default you cannot create/alter/destroy instances because they are cached in memory.
|
207
|
+
Because of Rails' process-based model it is not safe to allow updating acts\_as\_enumerated records as the caches will get out of sync.
|
189
208
|
|
190
209
|
However, one instance where updating the models *should* be allowed is if you are using seeds.rb to seed initial values into the database.
|
191
210
|
|
@@ -196,64 +215,76 @@ Using the above example you would do the following:
|
|
196
215
|
BookingStatus.create( :name => status_name )
|
197
216
|
end
|
198
217
|
|
199
|
-
|
218
|
+
Note that a `:presence` and `:uniqueness` validation is automatically defined on each model for the name column.
|
200
219
|
|
201
|
-
###
|
220
|
+
### has\_enumerated
|
202
221
|
|
203
|
-
First of all, note that you *could* specify the relationship to an acts_as_enumerated class using the belongs_to association.
|
222
|
+
First of all, note that you *could* specify the relationship to an `acts_as_enumerated` class using the belongs_to association.
|
223
|
+
However, `has_enumerated` is preferable because you aren't really associated to the enumerated value, you are *aggregating* it. As such,
|
224
|
+
the `has_enumerated` macro behaves more like an aggregation than an association.
|
204
225
|
|
205
226
|
class Booking < ActiveRecord::Base
|
206
|
-
has_enumerated :status, :class_name
|
207
|
-
|
208
|
-
|
227
|
+
has_enumerated :status, :class_name => 'BookingStatus',
|
228
|
+
:foreign_key => 'status_id',
|
229
|
+
:on_lookup_failure => :optional_instance_method
|
209
230
|
end
|
210
231
|
|
211
|
-
By default, the foreign key is interpreted to be the name of your
|
232
|
+
By default, the foreign key is interpreted to be the name of your has\_enumerated field (in this case 'status') plus '\_id'. Additionally,
|
233
|
+
the default value for `:class_name` is the camel-ized version of the name for your has\_enumerated field. `:on_lookup_failure` is explained below.
|
212
234
|
|
213
235
|
With that, your Booking class will have the following methods defined:
|
214
236
|
|
215
|
-
#### status
|
237
|
+
#### `status`
|
216
238
|
|
217
239
|
Returns the BookingStatus with an id that matches the value in the Booking.status_id.
|
218
240
|
|
219
|
-
#### status=(arg)
|
241
|
+
#### `status=(arg)`
|
220
242
|
|
221
|
-
Sets the value for Booking.status_id using the id of the BookingStatus instance passed as an argument. As a
|
243
|
+
Sets the value for Booking.status_id using the id of the BookingStatus instance passed as an argument. As a
|
244
|
+
short-hand, you can also pass it the 'name' of a BookingStatus instance, either as a 'string' or :symbol, or pass in the id directly.
|
222
245
|
|
223
246
|
example:
|
224
247
|
|
225
248
|
mybooking.status = :confirmed
|
226
249
|
|
227
|
-
this
|
250
|
+
this is equivalent to:
|
228
251
|
|
229
252
|
mybooking.status = 'confirmed'
|
230
253
|
|
231
|
-
|
254
|
+
or:
|
255
|
+
|
256
|
+
mybooking.status = BookingStatus[:confirmed]
|
257
|
+
|
258
|
+
The `:on_lookup_failure` option in has_enumerated is there because you may want to create an error handler for situations
|
259
|
+
where the argument passed to `status=(arg)` is invalid. By default, an invalid value will cause an ArgumentError to be raised.
|
232
260
|
|
233
261
|
Of course, this may not be optimal in your situation. In this case you can specify an *instance* method to be called in the case of a lookup failure. The method signature is as follows:
|
234
262
|
|
235
263
|
your_lookup_handler(operation, name, name_foreign_key, acts_enumerated_class_name, lookup_value)
|
236
264
|
|
237
|
-
The 'operation' arg will be either
|
265
|
+
The 'operation' arg will be either `:read` or `:write`. In the case of `:read` you are expected to return something or raise an exception,
|
266
|
+
while in the case of a `:write` you don't have to return anything.
|
238
267
|
|
239
|
-
Note that there's enough information in the method signature that you can specify one method to handle all lookup failures
|
268
|
+
Note that there's enough information in the method signature that you can specify one method to handle all lookup failures
|
269
|
+
for all has\_enumerated fields if you happen to have more than one defined in your model.
|
240
270
|
|
241
|
-
NOTE: A nil is always considered to be a valid value for status= since it's assumed you're trying to null out the foreign key
|
271
|
+
NOTE: A `nil` is always considered to be a valid value for `status=(arg)` since it's assumed you're trying to null out the foreign key.
|
272
|
+
The `:on_lookup_failure` will be bypassed.
|
242
273
|
|
243
274
|
### ActiveRecord::VirtualEnumerations
|
244
275
|
|
245
|
-
|
276
|
+
In many instances, your `acts_as_enumerated` classes will do nothing more than just act as enumerated.
|
246
277
|
|
247
278
|
In that case there isn't much point cluttering up your models directory with those class files. You can use ActiveRecord::VirtualEnumerations to reduce that clutter.
|
248
279
|
|
249
|
-
Copy
|
280
|
+
Copy virtual\_enumerations\_sample.rb to Rails.root/config/initializers/virtual\_enumerations.rb and configure it accordingly.
|
250
281
|
|
251
|
-
See
|
282
|
+
See virtual\_enumerations\_sample.rb in the examples directory of this gem for a full description.
|
252
283
|
|
253
284
|
|
254
285
|
## How to run tests
|
255
286
|
|
256
|
-
Go to dummy project:
|
287
|
+
Go to the 'dummy' project:
|
257
288
|
|
258
289
|
cd ./spec/dummy
|
259
290
|
|
@@ -277,7 +308,7 @@ And finally run tests:
|
|
277
308
|
|
278
309
|
* Initial Version Copyright (c) 2005 Trevor Squires
|
279
310
|
* Rails 3 Updates Copyright (c) 2010 Pivotal Labs
|
280
|
-
* Initial
|
281
|
-
*
|
311
|
+
* Initial Test Suite Copyright (c) 2011 Sergey Potapov
|
312
|
+
* Subsequent Updates Copyright (c) 2011 Arthur Shagall
|
282
313
|
|
283
314
|
Released under the MIT License. See the LICENSE file for more details.
|
@@ -25,6 +25,8 @@ module PowerEnum::Schema
|
|
25
25
|
# Set this to define the limit of the description column.
|
26
26
|
# [:active]
|
27
27
|
# Set this to <tt>true</tt> to have a boolean 'active' column generated. The 'active' column will have the options of NOT NULL and DEFAULT TRUE.
|
28
|
+
# [:timestamps]
|
29
|
+
# Set this to <tt>true</tt> to have timestamp columns (created_at and updated_at) generated.
|
28
30
|
#
|
29
31
|
# ===== Examples
|
30
32
|
# ====== Basic Enum
|
@@ -32,11 +34,15 @@ module PowerEnum::Schema
|
|
32
34
|
# is the equivalent of
|
33
35
|
# create_table :connector_types do |t|
|
34
36
|
# t.string :name, :null => false
|
35
|
-
# t.timestamps
|
36
37
|
# end
|
37
38
|
#
|
38
39
|
# ====== Advanced Enum
|
39
|
-
# create_enum :connector_type, :name_column => :connector,
|
40
|
+
# create_enum :connector_type, :name_column => :connector,
|
41
|
+
# :name_limit => 50,
|
42
|
+
# :description => true,
|
43
|
+
# :desc_limit => 100,
|
44
|
+
# :active => true,
|
45
|
+
# :timestamps => true
|
40
46
|
# is the equivalent of
|
41
47
|
# create_table :connector_types do |t|
|
42
48
|
# t.string :connector, :limit => 50, :null => false
|
@@ -50,6 +56,7 @@ module PowerEnum::Schema
|
|
50
56
|
name_column = options[:name_column] || :name
|
51
57
|
generate_description = !!options[:description]
|
52
58
|
generate_active = !!options[:active]
|
59
|
+
generate_timestamps = !!options[:timestamps]
|
53
60
|
name_limit = options[:name_limit]
|
54
61
|
desc_limit = options[:desc_limit]
|
55
62
|
|
@@ -61,8 +68,9 @@ module PowerEnum::Schema
|
|
61
68
|
if generate_active
|
62
69
|
t.boolean :active, :null => false, :default => true
|
63
70
|
end
|
64
|
-
|
65
|
-
|
71
|
+
if generate_timestamps
|
72
|
+
t.timestamps
|
73
|
+
end
|
66
74
|
end
|
67
75
|
|
68
76
|
add_index enum_table_name, [name_column], :unique => true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: power_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2011-09-
|
15
|
+
date: 2011-09-25 00:00:00.000000000Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
19
|
-
requirement: &
|
19
|
+
requirement: &28153380 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: 3.0.0
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *28153380
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: jeweler
|
30
|
-
requirement: &
|
30
|
+
requirement: &28152380 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: '0'
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *28152380
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: rspec
|
41
|
-
requirement: &
|
41
|
+
requirement: &28151860 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: '0'
|
47
47
|
type: :development
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *28151860
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: sqlite3
|
52
|
-
requirement: &
|
52
|
+
requirement: &28151280 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ! '>='
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
version: '0'
|
58
58
|
type: :development
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *28151280
|
61
61
|
description: ! 'Power Enum allows you to treat instances of your ActiveRecord models
|
62
62
|
as though they were an enumeration of values.
|
63
63
|
|