iron-enum 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/README.rdoc +12 -2
- data/Version.txt +1 -1
- data/lib/iron/enum/attr_support.rb +27 -20
- data/lib/iron/enum/core.rb +1 -1
- data/spec/enum/attr_spec.rb +4 -0
- data/spec/enum/enum_spec.rb +10 -0
- data/spec/enum/model_spec.rb +16 -0
- metadata +1 -1
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -12,7 +12,7 @@ Managing constants - status flags, system states, etc - is frustrating when work
|
|
12
12
|
with Ruby and Rails. The canonical solution is to use class constants. But doing so
|
13
13
|
leaves a lot to be desired. This gem provides a much more Ruby-like way of dealing
|
14
14
|
with magic constants, that provides symbol/key-based lookup, automatic conversion between
|
15
|
-
keys and values, user-friendly naming,
|
15
|
+
keys and values, user-friendly naming, attribute support, model scoping and validation, and more.
|
16
16
|
|
17
17
|
To use:
|
18
18
|
|
@@ -48,7 +48,7 @@ To use:
|
|
48
48
|
=> :shipped
|
49
49
|
|
50
50
|
# Validate values against the set of good values
|
51
|
-
>> OrderStatus.
|
51
|
+
>> OrderStatus.valid_value?(10)
|
52
52
|
=> false
|
53
53
|
|
54
54
|
# Get an array of all valid values
|
@@ -73,11 +73,21 @@ To use:
|
|
73
73
|
# Set a value
|
74
74
|
>> @order.status_returned!
|
75
75
|
=> 5
|
76
|
+
|
77
|
+
# Setting an invalid value raises an exception
|
78
|
+
# This raises RuntimeError('Unknown key or value [27] in enum OrderStatus')
|
79
|
+
>> @order.status = 27
|
76
80
|
|
77
81
|
# You even get free scoping
|
78
82
|
>> Order.with_status(:shipped)
|
79
83
|
=> [...all orders with status == 4...]
|
80
84
|
|
85
|
+
# And model validation, should you somehow set the field to an improper value
|
86
|
+
>> @order = Order.new
|
87
|
+
>> @order.send(:write_attribute, :status, -2)
|
88
|
+
>> @order.valid?
|
89
|
+
=> false
|
90
|
+
|
81
91
|
== REQUIREMENTS
|
82
92
|
|
83
93
|
None, though you'll need rspec, sqlite3 and active_record gems to test and build the gem
|
data/Version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
@@ -45,13 +45,13 @@ module Enum
|
|
45
45
|
module AttrSupport
|
46
46
|
|
47
47
|
# Call with enum_attr :field => Enum
|
48
|
-
def enum_attr(
|
48
|
+
def enum_attr(field_to_enum_map)
|
49
49
|
# Save off the attr map
|
50
50
|
@enum_attrs ||= {}
|
51
|
-
@enum_attrs.merge!(
|
51
|
+
@enum_attrs.merge!(field_to_enum_map)
|
52
52
|
|
53
53
|
# Run each newly added enum attribute
|
54
|
-
|
54
|
+
field_to_enum_map.each_pair do |attr_field, enum|
|
55
55
|
# Convert Enum to "Enum"
|
56
56
|
enum_klass = enum.to_s
|
57
57
|
|
@@ -59,12 +59,12 @@ module Enum
|
|
59
59
|
# attr_as_key to get back eg :production or :online instead of 1 or 5
|
60
60
|
# attr_as_name to get back eg "Production" or "Online"
|
61
61
|
class_eval <<-eos, __FILE__, __LINE__ + 1
|
62
|
-
def #{
|
63
|
-
#{enum_klass}.key(self.#{
|
62
|
+
def #{attr_field}_as_key
|
63
|
+
#{enum_klass}.key(self.#{attr_field})
|
64
64
|
end
|
65
65
|
|
66
|
-
def #{
|
67
|
-
#{enum_klass}.name(self.#{
|
66
|
+
def #{attr_field}_as_name
|
67
|
+
#{enum_klass}.name(self.#{attr_field})
|
68
68
|
end
|
69
69
|
eos
|
70
70
|
|
@@ -75,12 +75,12 @@ module Enum
|
|
75
75
|
|
76
76
|
# Build sugar for testing and setting the attribute's enumerated value
|
77
77
|
class_eval <<-eos, __FILE__, __LINE__ + 1
|
78
|
-
def #{
|
79
|
-
self.#{
|
78
|
+
def #{attr_field}_#{key}?
|
79
|
+
self.#{attr_field} == #{val}
|
80
80
|
end
|
81
81
|
|
82
|
-
def #{
|
83
|
-
self.#{
|
82
|
+
def #{attr_field}_#{key}!
|
83
|
+
self.#{attr_field} = #{val}
|
84
84
|
end
|
85
85
|
eos
|
86
86
|
end
|
@@ -88,21 +88,28 @@ module Enum
|
|
88
88
|
if defined?(ActiveRecord) && self < ActiveRecord::Base
|
89
89
|
|
90
90
|
# Define a finder scope
|
91
|
-
scope "with_#{
|
91
|
+
scope "with_#{attr_field}", lambda {|*vals|
|
92
92
|
vals.flatten!
|
93
93
|
if vals.empty?
|
94
94
|
where("?", false)
|
95
95
|
elsif vals.count == 1
|
96
|
-
where(
|
96
|
+
where(attr_field => enum.value(vals.first))
|
97
97
|
else
|
98
|
-
where(
|
98
|
+
where(attr_field => enum.values(vals))
|
99
99
|
end
|
100
100
|
}
|
101
|
+
|
102
|
+
# Define a validation
|
103
|
+
validates attr_field, :inclusion => {
|
104
|
+
:in => enum.values,
|
105
|
+
:message => "%{value} is not a valid #{enum_klass} value",
|
106
|
+
:allow_nil => true
|
107
|
+
}
|
101
108
|
|
102
109
|
# Override default setter to allow setting an enum attribute via key
|
103
110
|
class_eval <<-eos, __FILE__, __LINE__ + 1
|
104
|
-
def #{
|
105
|
-
write_attribute(:#{
|
111
|
+
def #{attr_field}=(val)
|
112
|
+
write_attribute(:#{attr_field}, #{enum_klass}.value(val))
|
106
113
|
end
|
107
114
|
eos
|
108
115
|
|
@@ -110,12 +117,12 @@ module Enum
|
|
110
117
|
|
111
118
|
# Create getter/setter to allow setting an enum attribute via key
|
112
119
|
class_eval <<-eos, __FILE__, __LINE__ + 1
|
113
|
-
def #{
|
114
|
-
@#{
|
120
|
+
def #{attr_field}
|
121
|
+
@#{attr_field}
|
115
122
|
end
|
116
123
|
|
117
|
-
def #{
|
118
|
-
@#{
|
124
|
+
def #{attr_field}=(val)
|
125
|
+
@#{attr_field} = #{enum_klass}.value(val)
|
119
126
|
end
|
120
127
|
eos
|
121
128
|
|
data/lib/iron/enum/core.rb
CHANGED
@@ -82,7 +82,7 @@ module Enum
|
|
82
82
|
def row_for(in_key)
|
83
83
|
key = to_key(in_key)
|
84
84
|
row = enum_list.find {|r| r[KEY_IDX] == key}
|
85
|
-
raise "
|
85
|
+
raise RuntimeError.new("Unknown key or value [#{in_key.inspect}] in enum #{self}") unless row
|
86
86
|
row
|
87
87
|
end
|
88
88
|
|
data/spec/enum/attr_spec.rb
CHANGED
data/spec/enum/enum_spec.rb
CHANGED
@@ -25,5 +25,15 @@ describe Enum do
|
|
25
25
|
EnumTest.valid_value?(10).should be_true
|
26
26
|
EnumTest.valid_value?(555).should be_false
|
27
27
|
end
|
28
|
+
|
29
|
+
it 'should enforce proper keys' do
|
30
|
+
expect { EnumTest.enum('not-a-key', 27) }.to raise_error
|
31
|
+
expect { EnumTest.enum(27, 100) }.to raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should enforce proper values' do
|
35
|
+
expect { EnumTest.enum(:some_key, nil) }.to raise_error
|
36
|
+
expect { EnumTest.enum(:some_key, '200') }.to raise_error
|
37
|
+
end
|
28
38
|
|
29
39
|
end
|
data/spec/enum/model_spec.rb
CHANGED
@@ -53,6 +53,7 @@ describe Enum do
|
|
53
53
|
|
54
54
|
it 'should support multiple values in the automatic scope' do
|
55
55
|
ARTest.delete_all
|
56
|
+
ARTest.create!(:enum_field => :one)
|
56
57
|
ARTest.create!(:enum_field => :two)
|
57
58
|
ARTest.create!(:enum_field => 33)
|
58
59
|
ARTest.with_enum_field(2, :thirty_three).count.should == 2
|
@@ -75,5 +76,20 @@ describe Enum do
|
|
75
76
|
ARTest.with_enum_field(nil).count.should == 1
|
76
77
|
end
|
77
78
|
|
79
|
+
it 'should fail validation with invalid values' do
|
80
|
+
@test.send(:write_attribute, :enum_field, 270)
|
81
|
+
@test.should_not be_valid
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should pass validation with valid values' do
|
85
|
+
@test.send(:write_attribute, :enum_field, AREnum::TWO)
|
86
|
+
@test.should be_valid
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should pass validation with a nil value' do
|
90
|
+
@test.send(:write_attribute, :enum_field, nil)
|
91
|
+
@test.should be_valid
|
92
|
+
end
|
93
|
+
|
78
94
|
end
|
79
95
|
end
|