iron-enum 1.0.0 → 1.0.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/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
|