classy_enum 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +96 -32
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/classy_enum.gemspec +4 -5
- data/generators/classy_enum_generator.rb +1 -1
- data/generators/templates/enum.rb +2 -2
- data/lib/classy_enum.rb +122 -16
- data/lib/classy_enum/attributes.rb +19 -2
- data/lib/classy_enum/semantic_form_builder.rb +5 -5
- data/lib/generators/classy_enum/classy_enum_generator.rb +1 -1
- data/lib/generators/classy_enum/templates/enum.rb +2 -2
- data/spec/classy_enum_attributes_spec.rb +10 -6
- data/spec/classy_enum_semantic_form_builder_spec.rb +18 -18
- data/spec/classy_enum_spec.rb +48 -41
- data/spec/spec_helper.rb +1 -1
- metadata +8 -8
data/README.textile
CHANGED
@@ -16,66 +16,84 @@ h2. Example Usage
|
|
16
16
|
|
17
17
|
The most common use for ClassyEnum is to replace database lookup tables where the content and behavior is mostly static and has multiple "types". In this example, I have an ActiveRecord model called @Alarm@ with an attribute called @priority@. Priority is stored as a string (VARCHAR) type in the database and is converted to an enum value when requested.
|
18
18
|
|
19
|
+
h3. 1. Generate the Enum
|
20
|
+
|
19
21
|
The fastest way to get up and running with ClassyEnum is to use the built-in Rails generator like so:
|
20
22
|
|
21
23
|
Rails 2.3.x:
|
22
24
|
|
23
25
|
<pre>
|
24
|
-
script/generate classy_enum
|
26
|
+
script/generate classy_enum Priority low medium high
|
25
27
|
</pre>
|
26
28
|
|
27
29
|
Rails 3.x
|
28
30
|
|
29
31
|
<pre>
|
30
|
-
rails g classy_enum
|
32
|
+
rails g classy_enum Priority low medium high
|
31
33
|
</pre>
|
32
34
|
|
33
|
-
A new file will be created at app/enums/
|
35
|
+
A new enum template file will be created at app/enums/priority.rb that will look like:
|
34
36
|
|
35
37
|
<pre>
|
36
|
-
class
|
38
|
+
class Priority < ClassyEnum::Base
|
37
39
|
enum_classes :low, :medium, :high
|
38
40
|
end
|
39
41
|
|
40
|
-
class
|
42
|
+
class PriorityLow < Priority
|
41
43
|
end
|
42
44
|
|
43
|
-
class
|
45
|
+
class PriorityMedium < Priority
|
44
46
|
end
|
45
47
|
|
46
|
-
class
|
48
|
+
class PriorityHigh < Priority
|
47
49
|
end
|
48
50
|
</pre>
|
49
51
|
|
50
|
-
|
52
|
+
The @enum_classes@ macro will add all the ClassyEnum behavior, which is described further down in this document.
|
53
|
+
|
54
|
+
h3. 2. Customize the Enum
|
55
|
+
|
56
|
+
The generator creates a default setup, but each enum member can be changed to fit your needs.
|
51
57
|
|
52
|
-
Using the @enum_classes@ method, I have defined three priority levels: low, medium, and high. Each priority level can have different properties and methods associated with it.
|
58
|
+
Using the @enum_classes@ method, I have defined three priority levels: low, medium, and high. Each priority level can have different properties and methods associated with it.
|
59
|
+
|
60
|
+
I would like to add a method called @send_email?@ that all member subclasses respond to. By default this method will return false, but will be overridden for high priority alarms to return true.
|
53
61
|
|
54
62
|
<pre>
|
55
|
-
class
|
63
|
+
class Priority < ClassyEnum::Base
|
56
64
|
enum_classes :low, :medium, :high
|
57
|
-
|
58
|
-
def
|
65
|
+
|
66
|
+
def send_email?
|
59
67
|
false
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
63
|
-
class
|
64
|
-
def
|
71
|
+
class PriorityHigh < Priority
|
72
|
+
def send_email?
|
65
73
|
true
|
66
74
|
end
|
67
75
|
end
|
68
76
|
</pre>
|
69
77
|
|
70
|
-
|
78
|
+
Note: Defining the subclasses within your enum file is only required when you will be overriding behavior and/or properties. The member subclasses still exist without being defined here because ClassyEnum.enum_classes automatically creates a class for each member. The generator only creates these subclass definitions for convenience, but they can be deleted as shown in this example.
|
79
|
+
|
80
|
+
h3. 3. Setup the ActiveRecord model
|
81
|
+
|
82
|
+
My ActiveRecord Alarm model needs a text field that will store a string representing the enum member. An example model schema might look something like:
|
83
|
+
|
84
|
+
<pre>
|
85
|
+
create_table "alarms", :force => true do |t|
|
86
|
+
t.string "priority"
|
87
|
+
end
|
88
|
+
</pre>
|
71
89
|
|
72
|
-
|
90
|
+
Then in my model I've added a line that calls @classy_enum_attr@ with a single argument representing the enum I want to associate with my model. I am also delegating the send_email? method to my Priority enum class.
|
73
91
|
|
74
92
|
<pre>
|
75
93
|
class Alarm < ActiveRecord::Base
|
76
|
-
classy_enum_attr :
|
77
|
-
|
78
|
-
delegate :
|
94
|
+
classy_enum_attr :priority
|
95
|
+
|
96
|
+
delegate :send_email?, :to => :priority
|
79
97
|
end
|
80
98
|
</pre>
|
81
99
|
|
@@ -83,14 +101,64 @@ With this setup, I can now do the following:
|
|
83
101
|
|
84
102
|
<pre>
|
85
103
|
@alarm = Alarm.create(:priority => :medium)
|
86
|
-
|
87
|
-
@alarm.priority =>
|
88
|
-
|
89
|
-
@alarm.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
@alarm.
|
104
|
+
|
105
|
+
@alarm.priority # => PriorityMedium
|
106
|
+
@alarm.priority.is? :medium # => true
|
107
|
+
@alarm.priority.to_s # => 'medium'
|
108
|
+
@alarm.priority.name # => 'Medium'
|
109
|
+
|
110
|
+
# Should this alarm send an email?
|
111
|
+
@alarm.send_email? # => false
|
112
|
+
@alarm.priority = :high
|
113
|
+
@alarm.send_email? # => true
|
114
|
+
</pre>
|
115
|
+
|
116
|
+
The enum field works like any other model attribute. It can be mass-assigned using @update_attribute(s)@.
|
117
|
+
|
118
|
+
h2. Special Cases
|
119
|
+
|
120
|
+
What if your enum class name is not the same as your model's attribute name? No problem! Just use a second arugment in @classy_enum_attr@ to declare the attribute name. In this case, the model's attribute is called *alarm_priority*.
|
121
|
+
|
122
|
+
<pre>
|
123
|
+
class Alarm < ActiveRecord::Base
|
124
|
+
classy_enum_attr :priority, :alarm_priority
|
125
|
+
end
|
126
|
+
|
127
|
+
@alarm = Alarm.create(:alarm_priority => :medium)
|
128
|
+
@alarm.alarm_priority # => PriorityMedium
|
129
|
+
</pre>
|
130
|
+
|
131
|
+
h2. Model Validation
|
132
|
+
|
133
|
+
An ActiveRecord validator @validates_inclusion_of :field, :in => ENUM.all, :allow_nil => true@ is automatically added to your model when you use @classy_enum_attr@.
|
134
|
+
|
135
|
+
If your enum only has members low, mediume, and high, then the following validation behavior would be expected:
|
136
|
+
|
137
|
+
<pre>
|
138
|
+
@alarm = Alarm.new(:priority => :really_high)
|
139
|
+
@alarm.valid? # => false
|
140
|
+
@alarm.priority = :high
|
141
|
+
@alarm.valid? # => true
|
142
|
+
</pre>
|
143
|
+
|
144
|
+
h2. Working with ClassyEnum outside of ActiveRecord
|
145
|
+
|
146
|
+
While ClassyEnum was designed to be used directly with ActiveRecord, it can also be used outside of it. Here are some examples based on the enum class defined earlier in this document.
|
147
|
+
|
148
|
+
Instantiate an enum member subclass *PriorityLow*
|
149
|
+
|
150
|
+
<pre>
|
151
|
+
# These statements are all equivalent
|
152
|
+
low = Priority.build(:low)
|
153
|
+
low = Priority.build('low)
|
154
|
+
low = Priority.find(:low)
|
155
|
+
low = PriorityLow.new
|
156
|
+
</pre>
|
157
|
+
|
158
|
+
Get a list of the valid enum options
|
159
|
+
|
160
|
+
<pre>
|
161
|
+
Priority.valid_options # => low, mediume, high
|
94
162
|
</pre>
|
95
163
|
|
96
164
|
h2. Formtastic Support
|
@@ -103,10 +171,6 @@ Formtastic::SemanticFormHelper.builder = ClassyEnum::SemanticFormBuilder
|
|
103
171
|
|
104
172
|
Then in your Formtastic view forms, use this syntax: @<%= f.input :priority, :as => :enum_select %>@
|
105
173
|
|
106
|
-
h2. Notes
|
107
|
-
|
108
|
-
An ActiveRecord validator @validates_inclusion_of :field, :in => ENUM.all, :allow_nil => true@ is automatically added to your model when you use @classy_enum_attr@.
|
109
|
-
|
110
174
|
h2. Copyright
|
111
175
|
|
112
|
-
Copyright (c)
|
176
|
+
Copyright (c) 2011 Peter Brown. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ begin
|
|
14
14
|
gem.add_development_dependency 'rspec-rails', '~> 2.0'
|
15
15
|
gem.add_development_dependency 'formtastic', '~> 1.1'
|
16
16
|
gem.add_development_dependency 'sqlite3-ruby'
|
17
|
-
gem.
|
17
|
+
gem.add_development_dependency "activerecord", ">= 2.3"
|
18
18
|
end
|
19
19
|
Jeweler::GemcutterTasks.new
|
20
20
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/classy_enum.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{classy_enum}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.7.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Peter Brown"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-29}
|
13
13
|
s.description = %q{A utility that adds class based enum functionality to ActiveRecord attributes}
|
14
14
|
s.email = %q{github@lette.us}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -42,7 +42,7 @@ Gem::Specification.new do |s|
|
|
42
42
|
s.homepage = %q{http://github.com/beerlington/classy_enum}
|
43
43
|
s.rdoc_options = ["--charset=UTF-8"]
|
44
44
|
s.require_paths = ["lib"]
|
45
|
-
s.rubygems_version = %q{1.
|
45
|
+
s.rubygems_version = %q{1.4.2}
|
46
46
|
s.summary = %q{A class based enumerator utility for Ruby on Rails}
|
47
47
|
s.test_files = [
|
48
48
|
"spec/classy_enum_attributes_spec.rb",
|
@@ -52,7 +52,6 @@ Gem::Specification.new do |s|
|
|
52
52
|
]
|
53
53
|
|
54
54
|
if s.respond_to? :specification_version then
|
55
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
55
|
s.specification_version = 3
|
57
56
|
|
58
57
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
@@ -60,7 +59,7 @@ Gem::Specification.new do |s|
|
|
60
59
|
s.add_development_dependency(%q<rspec-rails>, ["~> 2.0"])
|
61
60
|
s.add_development_dependency(%q<formtastic>, ["~> 1.1"])
|
62
61
|
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
63
|
-
s.
|
62
|
+
s.add_development_dependency(%q<activerecord>, [">= 2.3"])
|
64
63
|
else
|
65
64
|
s.add_dependency(%q<rspec>, ["~> 2.0"])
|
66
65
|
s.add_dependency(%q<rspec-rails>, ["~> 2.0"])
|
data/lib/classy_enum.rb
CHANGED
@@ -1,13 +1,30 @@
|
|
1
1
|
require "classy_enum/attributes"
|
2
2
|
|
3
3
|
if Gem.available? 'formtastic'
|
4
|
-
require 'formtastic'
|
4
|
+
require 'formtastic'
|
5
5
|
require 'classy_enum/semantic_form_builder'
|
6
6
|
end
|
7
7
|
|
8
8
|
module ClassyEnum
|
9
9
|
|
10
10
|
class Base
|
11
|
+
|
12
|
+
# Macro for defining enum members within a ClassyEnum class.
|
13
|
+
# Accepts an array of symbols or strings which are converted to
|
14
|
+
# ClassyEnum members as descents of their parent class.
|
15
|
+
#
|
16
|
+
# ==== Example
|
17
|
+
# # Define an enum called Priority with three child classes
|
18
|
+
# class Priority < ClassyEnum::Base
|
19
|
+
# enum_classes :low, :medium, :high
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# The child classes will be defined with the following constants:
|
23
|
+
# PriorityLow, PriorityMedium, and PriorityHigh
|
24
|
+
#
|
25
|
+
# These child classes can be instantiated with either:
|
26
|
+
# Priority.build(:low) or PriorityLow.new
|
27
|
+
#
|
11
28
|
def self.enum_classes(*options)
|
12
29
|
self.send(:attr_reader, :enum_classes)
|
13
30
|
|
@@ -18,6 +35,8 @@ module ClassyEnum
|
|
18
35
|
options.each_with_index do |option, index|
|
19
36
|
|
20
37
|
klass = Class.new(self) do
|
38
|
+
include InstanceMethods
|
39
|
+
|
21
40
|
attr_reader :to_s, :to_sym, :index
|
22
41
|
|
23
42
|
@index = index + 1
|
@@ -29,13 +48,6 @@ module ClassyEnum
|
|
29
48
|
@index = self.class.instance_variable_get('@index')
|
30
49
|
end
|
31
50
|
|
32
|
-
def name
|
33
|
-
@to_s.titleize
|
34
|
-
end
|
35
|
-
|
36
|
-
def <=> other
|
37
|
-
@index <=> other.index
|
38
|
-
end
|
39
51
|
end
|
40
52
|
|
41
53
|
klass_name = "#{self}#{option.to_s.camelize}"
|
@@ -45,29 +57,123 @@ module ClassyEnum
|
|
45
57
|
end
|
46
58
|
|
47
59
|
module ClassMethods
|
48
|
-
|
60
|
+
|
61
|
+
# Build a new ClassyEnum child instance
|
62
|
+
#
|
63
|
+
# ==== Example
|
64
|
+
# # Create an Enum with some elements
|
65
|
+
# class Priority < ClassyEnum::Base
|
66
|
+
# enum_classes :low, :medium, :high
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# Priority.build(:low) # => PriorityLow.new
|
49
70
|
def build(option)
|
50
71
|
return option if option.blank?
|
51
72
|
return TypeError.new("Valid #{self} options are #{self.valid_options}") unless self::OPTIONS.include? option.to_sym
|
52
73
|
Object.const_get("#{self}#{option.to_s.camelize}").new
|
53
74
|
end
|
54
|
-
|
55
|
-
# Alias of build
|
56
|
-
def find(option); build(option); end;
|
57
75
|
|
76
|
+
alias :find :build
|
77
|
+
|
78
|
+
# Returns an array of all instantiated enums
|
79
|
+
#
|
80
|
+
# ==== Example
|
81
|
+
# # Create an Enum with some elements
|
82
|
+
# class Priority < ClassyEnum::Base
|
83
|
+
# enum_classes :low, :medium, :high
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# Priority.all # => [PriorityLow.new, PriorityMedium.new, PriorityHigh.new]
|
58
87
|
def all
|
59
88
|
self::OPTIONS.map {|e| build(e) }
|
60
89
|
end
|
61
|
-
|
62
|
-
#
|
90
|
+
|
91
|
+
# Returns a 2D array for Rails select helper options.
|
92
|
+
# Also used internally for Formtastic support
|
93
|
+
#
|
94
|
+
# ==== Example
|
95
|
+
# # Create an Enum with some elements
|
96
|
+
# class Priority < ClassyEnum::Base
|
97
|
+
# enum_classes :low, :really_high
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# Priority.select_options # => [["Low", "low"], ["Really High", "really_high"]]
|
63
101
|
def select_options
|
64
102
|
all.map {|e| [e.name, e.to_s] }
|
65
103
|
end
|
66
|
-
|
104
|
+
|
105
|
+
# Returns a comma separated list of valid enum options.
|
106
|
+
# Also used internally for ActiveRecord model validation error messages
|
107
|
+
#
|
108
|
+
# ==== Example
|
109
|
+
# # Create an Enum with some elements
|
110
|
+
# class Priority < ClassyEnum::Base
|
111
|
+
# enum_classes :low, :medium, :high
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# Priority.valid_options # => "low, medium, high"
|
67
115
|
def valid_options
|
68
116
|
self::OPTIONS.map(&:to_s).join(', ')
|
69
117
|
end
|
70
|
-
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
module InstanceMethods
|
122
|
+
# Returns string representing enum in Rails titleize format
|
123
|
+
#
|
124
|
+
# ==== Example
|
125
|
+
# # Create an Enum with some elements
|
126
|
+
# class Priority < ClassyEnum::Base
|
127
|
+
# enum_classes :low, :medium, :high, :really_high
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# @priority = Priority.build(:really_high)
|
131
|
+
# @priority.name # => "Really High"
|
132
|
+
def name
|
133
|
+
@to_s.titleize
|
134
|
+
end
|
135
|
+
|
136
|
+
# Sort an array of elements based on the order they are defined
|
137
|
+
#
|
138
|
+
# ==== Example
|
139
|
+
# # Create an Enum with some elements
|
140
|
+
# class Priority < ClassyEnum::Base
|
141
|
+
# enum_classes :low, :medium, :high
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# @low = Priority.build(:low)
|
145
|
+
# @medium = Priority.build(:medium)
|
146
|
+
# @high = Priority.build(:high)
|
147
|
+
# priorities = [@low, @high, @medium]
|
148
|
+
# priorities.sort # => [@low, @medium, @high]
|
149
|
+
# priorities.max # => @high
|
150
|
+
# priorities.min # => @low
|
151
|
+
def <=> other
|
152
|
+
@index <=> other.index
|
153
|
+
end
|
154
|
+
|
155
|
+
# Determine if the enum attribute is a particular member.
|
156
|
+
# Accepts a symbol or string representing a member
|
157
|
+
#
|
158
|
+
# ==== Example
|
159
|
+
# # Create an Enum with some elements
|
160
|
+
# class Breed < ClassyEnum::Base
|
161
|
+
# enum_classes :golden_retriever, :snoop
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# # Create an ActiveRecord class using the Breed enum
|
165
|
+
# class Dog < ActiveRecord::Base
|
166
|
+
# classy_enum_attr :breed
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# @dog = Dog.new(:breed => :snoop)
|
170
|
+
# @dog.breed.is? :snoop # => true
|
171
|
+
# @dog.breed.is? 'snoop' # => true
|
172
|
+
# @dog.breed.is? :golden_retriever # => false
|
173
|
+
def is?(obj)
|
174
|
+
obj.to_s == to_s
|
175
|
+
end
|
176
|
+
|
71
177
|
end
|
72
178
|
|
73
179
|
end
|
@@ -1,6 +1,23 @@
|
|
1
1
|
module ClassyEnum
|
2
2
|
module Attributes
|
3
3
|
|
4
|
+
# Class macro used to associate an enum with an attribute on an ActiveRecord model.
|
5
|
+
# This method is automatically added to all ActiveRecord models when the classy_enum gem
|
6
|
+
# is installed. Accepts an argument for the enum class to be associated with
|
7
|
+
# the model. If the enum class name is different than the field name, then an optional
|
8
|
+
# field name can be passed. ActiveRecord validation is automatically added to ensure
|
9
|
+
# that a value is one of its pre-defined enum members.
|
10
|
+
#
|
11
|
+
# ==== Example
|
12
|
+
# # Associate an enum Priority with Alarm model's priority attribute
|
13
|
+
# class Alarm < ActiveRecord::Base
|
14
|
+
# classy_enum_attr :priority
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # Associate an enum Priority with Alarm model's alarm_priority attribute
|
18
|
+
# class Alarm < ActiveRecord::Base
|
19
|
+
# classy_enum_attr :priority, :alarm_priority
|
20
|
+
# end
|
4
21
|
def classy_enum_attr(klass, method=nil)
|
5
22
|
|
6
23
|
method ||= klass
|
@@ -14,12 +31,12 @@ module ClassyEnum
|
|
14
31
|
record.errors.add(attr_name, "must be one of #{klass.all.map(&:to_sym).join(', ')}") unless klass.all.map(&:to_s).include? value.to_s
|
15
32
|
end
|
16
33
|
|
17
|
-
# Define getter method
|
34
|
+
# Define getter method that returns a ClassyEnum instance
|
18
35
|
define_method method do
|
19
36
|
klass.build(super())
|
20
37
|
end
|
21
38
|
|
22
|
-
# Define setter method
|
39
|
+
# Define setter method that accepts either string or symbol for member
|
23
40
|
define_method "#{method}=" do |value|
|
24
41
|
super(value.to_s)
|
25
42
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ClassyEnum
|
2
|
-
class SemanticFormBuilder < Formtastic::SemanticFormBuilder
|
2
|
+
class SemanticFormBuilder < Formtastic::SemanticFormBuilder # :nodoc: all
|
3
3
|
def enum_select_input(method, options)
|
4
4
|
enum_class = object.send(method)
|
5
5
|
|
@@ -11,14 +11,14 @@ module ClassyEnum
|
|
11
11
|
options[:collection] = enum_class.class.superclass.select_options
|
12
12
|
options[:selected] = enum_class.to_s
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
options[:include_blank] = false
|
16
|
-
|
16
|
+
|
17
17
|
select_input(method, options)
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
21
|
-
module Error
|
20
|
+
|
21
|
+
module Error # :nodoc: all
|
22
22
|
def self.invalid_classy_enum_object(method)
|
23
23
|
raise "#{method} is not a ClassyEnum object"
|
24
24
|
end
|
@@ -14,9 +14,9 @@ describe "A Dog Collection" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "A Dog" do
|
17
|
-
|
17
|
+
|
18
18
|
before(:each) { @dog = Dog.new(:breed => :golden_retriever) }
|
19
|
-
|
19
|
+
|
20
20
|
it "should have an enumerable breed" do
|
21
21
|
@dog.breed.class.should == BreedGoldenRetriever
|
22
22
|
end
|
@@ -25,13 +25,17 @@ describe "A Dog" do
|
|
25
25
|
@dog.breed.should respond_to('enum_classes')
|
26
26
|
end
|
27
27
|
|
28
|
+
it "should know which member the enum is" do
|
29
|
+
@dog.breed.is?(:golden_retriever).should be_true
|
30
|
+
end
|
31
|
+
|
28
32
|
it "should be valid with a valid option" do
|
29
33
|
@dog.should be_valid
|
30
34
|
end
|
31
35
|
|
32
36
|
context "with an invalid breed option" do
|
33
37
|
before { @dog.breed = :golden_doodle }
|
34
|
-
|
38
|
+
|
35
39
|
it "should not be valid with an invalid option" do
|
36
40
|
@dog.should_not be_valid
|
37
41
|
end
|
@@ -40,17 +44,17 @@ describe "A Dog" do
|
|
40
44
|
@dog.valid?
|
41
45
|
@dog.errors.should include(:breed)
|
42
46
|
end
|
43
|
-
|
47
|
+
|
44
48
|
it "should have an error message containing the right options" do
|
45
49
|
@dog.valid?
|
46
50
|
@dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
|
47
51
|
end
|
48
52
|
end
|
49
|
-
|
53
|
+
|
50
54
|
end
|
51
55
|
|
52
56
|
class Thing < ActiveRecord::Base
|
53
|
-
classy_enum_attr :breed, :dog_breed
|
57
|
+
classy_enum_attr :breed, :dog_breed
|
54
58
|
end
|
55
59
|
|
56
60
|
describe "A Thing" do
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require "spec/spec_helper"
|
2
2
|
|
3
|
-
describe 'using enum_select input' do
|
3
|
+
describe 'using enum_select input' do
|
4
4
|
include FormtasticSpecHelper
|
5
|
-
|
5
|
+
|
6
6
|
Formtastic::SemanticFormHelper.builder = ClassyEnum::SemanticFormBuilder
|
7
7
|
|
8
8
|
# Copied from how formtastic tests its form helpers
|
@@ -12,9 +12,9 @@ describe 'using enum_select input' do
|
|
12
12
|
|
13
13
|
context "when building a form with a classy_enum select" do
|
14
14
|
before(:each) do
|
15
|
-
@output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
|
16
|
-
concat(builder.input(:breed, :as => :enum_select))
|
17
|
-
end
|
15
|
+
@output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
|
16
|
+
concat(builder.input(:breed, :as => :enum_select))
|
17
|
+
end
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should produce a form tag" do
|
@@ -34,9 +34,9 @@ describe 'using enum_select input' do
|
|
34
34
|
|
35
35
|
context "when building a form with a classy_enum select, but the existing value is nil" do
|
36
36
|
before(:each) do
|
37
|
-
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
38
|
-
concat(builder.input(:other_breed, :as => :enum_select, :enum_class => :breed))
|
39
|
-
end
|
37
|
+
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
38
|
+
concat(builder.input(:other_breed, :as => :enum_select, :enum_class => :breed))
|
39
|
+
end
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should produce a form tag" do
|
@@ -56,9 +56,9 @@ describe 'using enum_select input' do
|
|
56
56
|
|
57
57
|
context "when building a form with a classy_enum select, using the enum_attr option" do
|
58
58
|
before(:each) do
|
59
|
-
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
60
|
-
concat(builder.input(:breed, :as => :enum_select))
|
61
|
-
end
|
59
|
+
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
60
|
+
concat(builder.input(:breed, :as => :enum_select))
|
61
|
+
end
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should produce a form tag" do
|
@@ -78,19 +78,19 @@ describe 'using enum_select input' do
|
|
78
78
|
|
79
79
|
it "should raise an error if the attribute is not a ClassyEnum object" do
|
80
80
|
lambda do
|
81
|
-
@output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
|
82
|
-
concat(builder.input(:id, :as => :enum_select))
|
83
|
-
end
|
81
|
+
@output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
|
82
|
+
concat(builder.input(:id, :as => :enum_select))
|
83
|
+
end
|
84
84
|
end.should raise_error("id is not a ClassyEnum object")
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should raise an error if the attribute is not a ClassyEnum object and its value is nil" do
|
88
88
|
lambda do
|
89
|
-
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
90
|
-
concat(builder.input(:id, :as => :enum_select))
|
91
|
-
end
|
89
|
+
@output = semantic_form_for(Dog.new, :url => "/") do |builder|
|
90
|
+
concat(builder.input(:id, :as => :enum_select))
|
91
|
+
end
|
92
92
|
end.should raise_error("id is not a ClassyEnum object")
|
93
93
|
end
|
94
94
|
|
95
|
-
end
|
95
|
+
end
|
96
96
|
|
data/spec/classy_enum_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
class TestEnum < ClassyEnum::Base
|
4
4
|
enum_classes :one, :two, :three
|
5
|
-
|
5
|
+
|
6
6
|
def self.test_class_method?
|
7
7
|
false
|
8
8
|
end
|
@@ -22,63 +22,80 @@ class TestEnumTwo
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
describe
|
25
|
+
describe "A ClassyEnum Descendent" do
|
26
26
|
|
27
27
|
TestEnum::OPTIONS.each do |option|
|
28
28
|
it "should define a TestEnum#{option.to_s.capitalize} class" do
|
29
29
|
Object.const_defined?("TestEnum#{option.to_s.capitalize}").should be_true
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
it "should return an array of enums" do
|
34
34
|
TestEnum.all.map(&:class).should == [TestEnumOne, TestEnumTwo, TestEnumThree]
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
it "should return an array of enums for a select tag" do
|
38
38
|
TestEnum.select_options.should == TestEnum::OPTIONS.map {|o| [TestEnum.build(o).name, TestEnum.build(o).to_s] }
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
it "should return a type error when adding an invalid option" do
|
42
42
|
TestEnum.build(:invalid_option).class.should == TypeError
|
43
43
|
end
|
44
|
-
|
45
|
-
context "with a collection of enums" do
|
46
|
-
before(:each) do
|
47
|
-
@one = TestEnum.build(:one)
|
48
|
-
@two = TestEnum.build(:two)
|
49
|
-
@three = TestEnum.build(:three)
|
50
|
-
|
51
|
-
@unordered = [@one, @three, @two]
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should sort the enums" do
|
55
|
-
@unordered.sort.should == [@one, @two, @three]
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should find the max enum based on its order" do
|
59
|
-
@unordered.max.should == @three
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
44
|
+
|
63
45
|
it "should find an enum by symbol" do
|
64
46
|
TestEnum.find(:one).class.should == TestEnumOne
|
65
47
|
end
|
66
|
-
|
48
|
+
|
67
49
|
it "should find an enum by string" do
|
68
50
|
TestEnum.find("one").class.should == TestEnumOne
|
69
51
|
end
|
70
52
|
|
53
|
+
it "should create an instance with a string" do
|
54
|
+
TestEnum.build("one").should be_a(TestEnumOne)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "A collection of ClassyEnums" do
|
59
|
+
before(:each) do
|
60
|
+
@one = TestEnum.build(:one)
|
61
|
+
@two = TestEnum.build(:two)
|
62
|
+
@three = TestEnum.build(:three)
|
63
|
+
|
64
|
+
@unordered = [@one, @three, @two]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should sort the enums" do
|
68
|
+
@unordered.sort.should == [@one, @two, @three]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should find the max enum based on its order" do
|
72
|
+
@unordered.max.should == @three
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "A ClassyEnum element" do
|
77
|
+
it "should instantiate a member" do
|
78
|
+
TestEnumOne.new.should be_a(TestEnumOne)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should inherit the default class methods" do
|
82
|
+
TestEnumOne.test_class_method?.should be_false
|
83
|
+
end
|
71
84
|
end
|
72
85
|
|
73
86
|
describe "A ClassyEnum instance" do
|
74
87
|
before { @enum = TestEnum.build(:one) }
|
75
|
-
|
88
|
+
|
76
89
|
it "should build a TestEnum class" do
|
77
90
|
@enum.class.should == TestEnumOne
|
78
91
|
end
|
79
92
|
|
80
|
-
it "should
|
81
|
-
|
93
|
+
it "should return true for is_element?(:one)" do
|
94
|
+
@enum.is?(:one).should be_true
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should return true for is_element?('one')" do
|
98
|
+
@enum.is?('one').should be_true
|
82
99
|
end
|
83
100
|
|
84
101
|
it "should be a TestEnum" do
|
@@ -88,7 +105,7 @@ describe "A ClassyEnum instance" do
|
|
88
105
|
it "should convert to a string" do
|
89
106
|
@enum.to_s.should == "one"
|
90
107
|
end
|
91
|
-
|
108
|
+
|
92
109
|
it "should convert to a symbol" do
|
93
110
|
@enum.to_sym.should == :one
|
94
111
|
end
|
@@ -96,25 +113,15 @@ describe "A ClassyEnum instance" do
|
|
96
113
|
it "should have a name" do
|
97
114
|
@enum.name.should == "One"
|
98
115
|
end
|
99
|
-
|
116
|
+
|
100
117
|
it "should inherit the default instance methods" do
|
101
118
|
@enum.test_instance_method?.should be_false
|
102
119
|
end
|
103
|
-
|
104
|
-
it "should inherit the default class methods" do
|
105
|
-
TestEnumOne.test_class_method?.should be_false
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should create the same instance with a string or symbol" do
|
109
|
-
@enum_string = TestEnum.build("one")
|
110
|
-
|
111
|
-
@enum.class.should == @enum_string.class
|
112
|
-
end
|
113
120
|
end
|
114
121
|
|
115
122
|
describe "An ClassyEnumValue" do
|
116
123
|
before(:each) { @enum = TestEnum.build(:two) }
|
117
|
-
|
124
|
+
|
118
125
|
it "should override the default instance methods" do
|
119
126
|
@enum.test_instance_method?.should be_true
|
120
127
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: classy_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 3
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 0
|
10
|
+
version: 0.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Peter Brown
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-01-29 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
- 2
|
91
91
|
- 3
|
92
92
|
version: "2.3"
|
93
|
-
type: :
|
93
|
+
type: :development
|
94
94
|
version_requirements: *id005
|
95
95
|
description: A utility that adds class based enum functionality to ActiveRecord attributes
|
96
96
|
email: github@lette.us
|
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
requirements: []
|
154
154
|
|
155
155
|
rubyforge_project:
|
156
|
-
rubygems_version: 1.
|
156
|
+
rubygems_version: 1.4.2
|
157
157
|
signing_key:
|
158
158
|
specification_version: 3
|
159
159
|
summary: A class based enumerator utility for Ruby on Rails
|