Skip to content
Browse files

Merge branch 'v3'

  • Loading branch information...
2 parents 2ad4f40 + b7b9ed1 commit 16ed8da72dfaef0af3a2e2f5a10d0f6b95ad5ac4 @beerlington beerlington committed
View
1 .gitignore
@@ -15,3 +15,4 @@ spec/reports
test/tmp
test/version_tmp
tmp
+.DS_Store
View
12 CHANGELOG.md
@@ -1,5 +1,17 @@
# ClassyEnum Changelog
+## 3.0.0
+
+* Removing ClassyEnum::Base.enum_classes in favor of using enum
+ inheritance to setup classes
+* Removing ClassyEnum::Base.valid_options
+* Removing ClassyEnum::Base.find
+* Removing ClassyEnum::Base#name
+* Removing :suffix option from classy_enum_attr
+* Enforce use of namespacing for subclasses (Parent::Child < Parent)
+* Use require instead of autoload
+* Lots of code refactoring
+
## 2.3.0
* Deprecating ClassyEnum::Base#name (use to_s.titleize instead). `name` is
View
80 README.md
@@ -6,12 +6,12 @@ ClassyEnum is a Ruby on Rails gem that adds class-based enumerator functionality
## Rails & Ruby Versions Supported
-*Rails:*
+*Rails:* 3.0.x - 3.2.x
- * 3.0.x - 3.2.x: Fully tested in a production application.
- * 2.3.x: If you need support for Rails 2.3.x, please install [version 0.9.1](https://rubygems.org/gems/classy_enum/versions/0.9.1)
+*Ruby:* 1.8.7, 1.9.2 and 1.9.3
-*Ruby:* Ruby 1.8.7, 1.9.2, and 1.9.3 are tested and supported
+If you need support for Rails 2.3.x, please install [version 0.9.1](https://rubygems.org/gems/classy_enum/versions/0.9.1).
+Note: This branch is no longer maintained and will not get bug fixes or new features.
## Installation
@@ -19,15 +19,9 @@ The gem is hosted at [rubygems.org](https://rubygems.org/gems/classy_enum)
You will also need to add `app/enums` as an autoloadable path. This configuration will depend on which version of rails you are using.
-## Upgrading to 2.0
+## Upgrading?
-Prior to 2.0, enum classes were implicity defined and were only required
-when overriding methods or properties. As of 2.0, all enum classes must
-explicity subclass a child of ClassyEnum::Base. If you used the
-generator, there are no changes to the existing structure.
-
-Built-in Formtastic support has been removed. See the note at the
-bottom of this readme for more information how how to enable it.
+See the [wiki](https://github.com/beerlington/classy_enum/wiki/Upgrading) for notes about upgrading from previous versions.
## Example Usage
@@ -45,20 +39,19 @@ A new enum template file will be created at app/enums/priority.rb that will look
```ruby
class Priority < ClassyEnum::Base
- enum_classes :low, :medium, :high
end
-class PriorityLow < Priority
+class Priority::Low < Priority
end
-class PriorityMedium < Priority
+class Priority::Medium < Priority
end
-class PriorityHigh < Priority
+class Priority::High < Priority
end
```
-The `enum_classes` class macro will define the enum member order as well as additional ClassyEnum behavior, which is described further down in this document.
+The class order will define the enum member order as well as additional ClassyEnum behavior, which is described further down in this document.
### 2. Customize the Enum
@@ -70,20 +63,18 @@ I would like to add a method called `send_email?` that all member subclasses res
```ruby
class Priority < ClassyEnum::Base
- enum_classes :low, :medium, :high
-
def send_email?
false
end
end
-class PriorityLow < Priority
+class Priority::Low < Priority
end
-class PriorityMedium < Priority
+class Priority::Medium < Priority
end
-class PriorityHigh < Priority
+class Priority::High < Priority
def send_email?
true
end
@@ -119,11 +110,10 @@ With this setup, I can now do the following:
```ruby
@alarm = Alarm.create(:priority => :medium)
-@alarm.priority # => PriorityMedium
+@alarm.priority # => Priority::Medium
@alarm.priority.medium? # => true
@alarm.priority.high? # => false
@alarm.priority.to_s # => 'medium'
-@alarm.priority.name # => 'Medium'
# Should this alarm send an email?
@alarm.send_email? # => false
@@ -137,7 +127,7 @@ The enum field works like any other model attribute. It can be mass-assigned usi
In some cases you may want an enum class to reference the owning object
(an instance of the active record model). Think of it as a `belongs_to`
-relationship, where the enum can reference its owning object.
+relationship, where the enum belongs to the model.
By default, the back reference can be called using `owner`.
If you want to refer to the owner by a different name, you must explicitly declare
@@ -147,14 +137,11 @@ Example using the default `owner` method:
```ruby
class Priority < ClassyEnum::Base
- enum_classes :low, :medium, :high
end
-...
# low and medium subclasses omitted
-...
-class PriorityHigh < Priority
+class Priority::High < Priority
def send_email?
owner.enabled?
end
@@ -165,15 +152,12 @@ Example where the owner reference is explicitly declared:
```ruby
class Priority < ClassyEnum::Base
- enum_classes :low, :medium, :high
owner :alarm
end
-...
# low and medium subclasses omitted
-...
-class PriorityHigh < Priority
+class Priority::High < Priority
def send_email?
alarm.enabled?
end
@@ -213,28 +197,15 @@ end
## Special Cases
-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*.
+What if your enum class name is not the same as your model's attribute name? No problem! Just use a second argument in `classy_enum_attr` to declare the attribute name. In this case, the model's attribute is called *alarm_priority*.
```ruby
class Alarm < ActiveRecord::Base
- classy_enum_attr :alarm_priority, :enum => :priority
+ classy_enum_attr :alarm_priority, :enum => 'Priority'
end
@alarm = Alarm.create(:alarm_priority => :medium)
-@alarm.alarm_priority # => PriorityMedium
-```
-
-If you would like the default getter method to return a string, you can
-use the optional *:suffix* option for the enum getter:
-
-```ruby
-class Alarm < ActiveRecord::Base
- classy_enum_attr :priority, :suffix => 'type'
-end
-
-alarm = Alarm.create(:priority => :high)
-alarm.priority # => 'high'
-alarm.priority_type # instance of PriorityHigh enum
+@alarm.alarm_priority # => Priority::Medium
```
## Model Validation
@@ -265,20 +236,13 @@ end
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.
-Instantiate an enum member subclass *PriorityLow*
+Instantiate an enum member subclass *Priority::Low*
```ruby
# These statements are all equivalent
low = Priority.build(:low)
low = Priority.build('low')
-low = Priority.find(:low)
-low = PriorityLow.new
-```
-
-Get a list of the valid enum options
-
-```ruby
-Priority.valid_options # => low, medium, high
+low = Priority::Low.new
```
## Formtastic Support
View
2 classy_enum.gemspec
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
gem.add_dependency('rails', '>= 3.0')
- gem.add_development_dependency('rspec-rails', '~> 2.10.0')
+ gem.add_development_dependency('rspec-rails', '~> 2.11.0')
gem.add_development_dependency('sqlite3', '~> 1.3.6')
gem.add_development_dependency('json', '~> 1.6.5')
View
6 gemfiles/Gemfile.rails-3.0.x
@@ -1,8 +1,6 @@
source :rubygems
gem 'rails', '~> 3.0.0'
-gem 'rspec-rails', '~> 2.8.1'
-gem 'formtastic', '~> 1.2.4'
+gem 'rspec-rails', '~> 2.11.0'
gem 'sqlite3-ruby', :require => 'sqlite3'
-gem 'json', '~> 1.6.5'
-gem "jeweler", "~> 1.6.2"
+gem 'json', '~> 1.6.5'
View
6 gemfiles/Gemfile.rails-3.1.x
@@ -1,8 +1,6 @@
source :rubygems
gem 'rails', '~> 3.1.0'
-gem 'rspec-rails', '~> 2.8.1'
-gem 'formtastic', '~> 1.2.4'
+gem 'rspec-rails', '~> 2.11.0'
gem 'sqlite3'
-gem 'json', '~> 1.6.5'
-gem "jeweler", "~> 1.6.2"
+gem 'json', '~> 1.6.5'
View
6 gemfiles/Gemfile.rails-3.2.x
@@ -1,8 +1,6 @@
source :rubygems
gem 'rails', '~> 3.2.0'
-gem 'rspec-rails', '~> 2.8.1'
-gem 'formtastic', '~> 1.2.4'
+gem 'rspec-rails', '~> 2.11.0'
gem 'sqlite3'
-gem 'json', '~> 1.6.5'
-gem "jeweler", "~> 1.6.2"
+gem 'json', '~> 1.6.5'
View
13 lib/classy_enum.rb
@@ -1,8 +1,5 @@
-module ClassyEnum
- autoload :Base, 'classy_enum/base'
- autoload :InstanceMethods, 'classy_enum/instance_methods'
- autoload :ClassMethods, 'classy_enum/class_methods'
- autoload :Attributes, 'classy_enum/attributes'
-end
-
-ActiveRecord::Base.send :extend, ClassyEnum::Attributes
+require 'classy_enum/collection'
+require 'classy_enum/conversion'
+require 'classy_enum/predicate'
+require 'classy_enum/base'
+require 'classy_enum/active_record'
View
58 lib/classy_enum/active_record.rb
@@ -0,0 +1,58 @@
+module ClassyEnum
+ module ActiveRecord
+
+ # Class macro used to associate an enum with an attribute on an ActiveRecord model.
+ # This method is automatically added to all ActiveRecord models when the classy_enum gem
+ # is installed. Accepts an argument for the enum class to be associated with
+ # the model. ActiveRecord validation is automatically added to ensure
+ # that a value is one of its pre-defined enum members.
+ #
+ # ==== Example
+ # # Associate an enum Priority with Alarm model's priority attribute
+ # class Alarm < ActiveRecord::Base
+ # classy_enum_attr :priority
+ # end
+ #
+ # # Associate an enum Priority with Alarm model's alarm_priority attribute
+ # classy_enum_attr :alarm_priority, :enum => 'Priority'
+ #
+ # # Allow enum value to be nil
+ # classy_enum_attr :priority, :allow_nil => true
+ #
+ # # Allow enum value to be blank
+ # classy_enum_attr :priority, :allow_blank => true
+ def classy_enum_attr(attribute, options={})
+ enum = (options[:enum] || attribute).to_s.camelize.constantize
+ allow_blank = options[:allow_blank] || false
+ allow_nil = options[:allow_nil] || false
+ serialize_as_json = options[:serialize_as_json] || false
+
+ error_message = "must be #{enum.all.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ')}"
+
+ # Add ActiveRecord validation to ensure it won't be saved unless it's an option
+ validates_inclusion_of attribute,
+ :in => enum.all,
+ :message => error_message,
+ :allow_blank => allow_blank,
+ :allow_nil => allow_nil
+
+ # Define getter method that returns a ClassyEnum instance
+ define_method attribute do
+ enum.build(read_attribute(attribute),
+ :owner => self,
+ :serialize_as_json => serialize_as_json,
+ :allow_blank => (allow_blank || allow_nil)
+ )
+ end
+
+ # Define setter method that accepts either string or symbol for member
+ define_method "#{attribute}=" do |value|
+ value = value.to_s unless value.nil?
+ super(value)
+ end
+ end
+
+ end
+end
+
+ActiveRecord::Base.send :extend, ClassyEnum::ActiveRecord
View
72 lib/classy_enum/attributes.rb
@@ -1,72 +0,0 @@
-module ClassyEnum
- module Attributes
-
- # Class macro used to associate an enum with an attribute on an ActiveRecord model.
- # This method is automatically added to all ActiveRecord models when the classy_enum gem
- # is installed. Accepts an argument for the enum class to be associated with
- # the model. If the enum class name is different than the field name, then an optional
- # field name can be passed. ActiveRecord validation is automatically added to ensure
- # that a value is one of its pre-defined enum members.
- #
- # ==== Example
- # # Associate an enum Priority with Alarm model's priority attribute
- # class Alarm < ActiveRecord::Base
- # classy_enum_attr :priority
- # end
- #
- # # Associate an enum Priority with Alarm model's alarm_priority attribute
- # class Alarm < ActiveRecord::Base
- # classy_enum_attr :alarm_priority, :enum => :priority
- # end
- def classy_enum_attr(*args)
- options = args.extract_options!
-
- attribute = args[0]
-
- enum = options[:enum] || attribute
- allow_blank = options[:allow_blank] || false
- allow_nil = options[:allow_nil] || false
- serialize_as_json = options[:serialize_as_json] || false
-
- reader_method = attribute.to_s
-
- if options.has_key? :suffix
- ActiveSupport::Deprecation.warn(':suffix option for classy_enum_attr is deprecated, and will be removed in ClassyEnum 3.0.', caller)
- reader_method += "_#{options[:suffix]}"
- end
-
- klass = enum.to_s.camelize.constantize
-
- valid_attributes = reader_method == attribute.to_s ? klass.all : klass.all.map(&:to_s)
-
- self.instance_eval do
-
- # Add ActiveRecord validation to ensure it won't be saved unless it's an option
- validates_inclusion_of attribute,
- :in => valid_attributes,
- :message => "must be one of #{klass.valid_options}",
- :allow_blank => allow_blank,
- :allow_nil => allow_nil
-
- # Define getter method that returns a ClassyEnum instance
- define_method reader_method do
- klass.build(read_attribute(attribute), :owner => self, :serialize_as_json => serialize_as_json)
- end
-
- # Define setter method that accepts either string or symbol for member
- define_method "#{attribute}=" do |value|
- value = value.to_s unless value.nil?
- super(value)
- end
-
- # Store the enum options so it can be later retrieved by Formtastic
- define_method "#{attribute}_options" do
- {:enum => enum, :allow_blank => allow_blank}
- end
-
- end
-
- end
-
- end
-end
View
86 lib/classy_enum/base.rb
@@ -1,8 +1,88 @@
module ClassyEnum
+ class SubclassNameError < Exception; end
+
class Base
- extend ClassyEnum::ClassMethods
- include ClassyEnum::InstanceMethods
include Comparable
- include ActiveModel::AttributeMethods
+ include Conversion
+ include Predicate
+ include Collection
+
+ class_attribute :base_class
+ attr_accessor :owner, :serialize_as_json, :allow_blank
+
+ class << self
+ def inherited(klass)
+ if self == ClassyEnum::Base
+ klass.base_class = klass
+ else
+
+ # Ensure subclasses follow expected naming conventions
+ unless klass.name.start_with? "#{base_class.name}::"
+ raise SubclassNameError, "subclass must be namespaced with #{base_class.name}::"
+ end
+
+ # Add visit_EnumMember methods to support validates_uniqueness_of with enum field
+ # This is due to a bug in Rails where it uses the method result as opposed to the
+ # database value for validation scopes. A fix will be released in Rails 4, but
+ # this will remain until Rails 3.x is no longer prevalent.
+ Arel::Visitors::ToSql.class_eval do
+ define_method "visit_#{klass.name.split('::').join('_')}", lambda {|value| quote(value.to_s) }
+ end
+
+ # Convert from MyEnumClass::NumberTwo to :number_two
+ enum = klass.name.split('::').last.underscore.to_sym
+
+ Predicate.define_predicate_method(klass, enum)
+
+ klass.instance_variable_set('@option', enum)
+ end
+
+ super
+ end
+
+ # Used internally to build a new ClassyEnum child instance
+ # It is preferred that you use ChildClass.new instead
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority
+ # end
+ #
+ # Priority.build(:low) # => Priority::Low.new
+ # Priority.build(:invalid_option) # => :invalid_option
+ def build(value, options={})
+ return value if value.blank? && options[:allow_blank]
+
+ # Return the value if it is not a valid member
+ return value unless all.map(&:to_s).include? value.to_s
+
+ object = "#{base_class}::#{value.to_s.camelize}".constantize.new
+ object.owner = options[:owner]
+ object.serialize_as_json = options[:serialize_as_json]
+ object.allow_blank = options[:allow_blank]
+ object
+ end
+
+ # DSL setter method for overriding reference to enum owner (ActiveRecord model)
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # owner :alarm
+ # end
+ #
+ # class Priority::High < Priority
+ # def send_alarm?
+ # alarm.enabled?
+ # end
+ # end
+ def owner(owner)
+ define_method owner, lambda { @owner }
+ end
+ end
+
end
end
View
141 lib/classy_enum/class_methods.rb
@@ -1,141 +0,0 @@
-module ClassyEnum
- module ClassMethods
-
- # Macro for defining enum members within a ClassyEnum class.
- # Accepts an array of symbols or strings which are converted to
- # ClassyEnum members as descents of their parent class.
- #
- # ==== Example
- # # Define an enum called Priority with three child classes
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # The child classes will be defined with the following constants:
- # PriorityLow, PriorityMedium, and PriorityHigh
- #
- # These child classes can be instantiated with either:
- # Priority.build(:low) or PriorityLow.new
- #
- def enum_classes(*enums)
- ActiveSupport::Deprecation.warn('enum_classes is deprecated, and will be removed in ClassyEnum 3.0. It is no longer needed.', caller)
-
- self.class_eval do
- class_attribute :enum_options, :base_class
-
- self.enum_options = enums.map(&:to_sym)
- self.base_class = self
-
- # # Use ActiveModel::AttributeMethods to define attribute? methods
- attribute_method_suffix '?'
- define_attribute_methods enums
- end
- end
-
- def inherited(klass)
- return if self == ClassyEnum::Base
-
- # Add visit_EnumMember methods to support validates_uniqueness_of with enum field
- Arel::Visitors::ToSql.class_eval do
- define_method "visit_#{klass.name}", lambda {|value| quote(value.to_s) }
- end
-
- if klass.name.start_with? "#{base_class.name}::"
- enum = klass.name.split('::').last.underscore.to_sym
- else
- ActiveSupport::Deprecation.warn("The enum class name #{klass} is deprecated. ClassyEnum 3.0 will require subclasses to use the parent class as a namespace. Change it to #{base_class}::#{klass.name.gsub(base_class.name, '')}", caller)
- enum = klass.name.gsub(klass.base_class.name, '').underscore.to_sym
- end
-
- index = self.enum_options.index(enum) + 1
-
- klass.class_eval do
- @index = index
- @option = enum
-
- attr_accessor :owner, :serialize_as_json
- end
- end
-
- # Build a new ClassyEnum child instance
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # Priority.build(:low) # => PriorityLow.new
- def build(value, options={})
- return value if value.blank?
- return TypeError.new("Valid #{self} options are #{self.valid_options}") unless self.enum_options.include? value.to_sym
-
- # Temp hack until 3.0 to allow both namespaced and non-namespaced classes
- begin
- klass = "#{self}::#{value.to_s.camelize}".constantize
- rescue NameError
- klass = "#{self}#{value.to_s.camelize}".constantize
- end
-
- object = klass.new
- object.owner = options[:owner]
- object.serialize_as_json = options[:serialize_as_json]
- object
- end
-
- def find(value, options={})
- ActiveSupport::Deprecation.warn("find is deprecated, and will be removed in ClassyEnum 3.0. Use build(:member) instead.", caller)
- build(value, options)
- end
-
- # Returns an array of all instantiated enums
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # Priority.all # => [PriorityLow.new, PriorityMedium.new, PriorityHigh.new]
- def all
- self.enum_options.map {|e| build(e) }
- end
-
- # Returns a 2D array for Rails select helper options.
- # Also used internally for Formtastic support
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :really_high
- # end
- #
- # Priority.select_options # => [["Low", "low"], ["Really High", "really_high"]]
- def select_options
- all.map {|e| [e.name, e.to_s] }
- end
-
- # Returns a comma separated list of valid enum options.
- # Also used internally for ActiveRecord model validation error messages
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # Priority.valid_options # => "low, medium, high"
- def valid_options
- ActiveSupport::Deprecation.warn("valid_options is deprecated, and will be removed in ClassyEnum 3.0. Use all.join(', ') instead.", caller)
- self.enum_options.map(&:to_s).join(', ')
- end
-
- private
-
- # DSL setter method for reference to enum owner
- def owner(owner)
- define_method owner, lambda { @owner }
- end
-
- end
-end
View
76 lib/classy_enum/collection.rb
@@ -0,0 +1,76 @@
+module ClassyEnum
+ module Collection
+ # Sort an array of elements based on the order they are defined
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::Medium < Priority; end
+ # class Priority::High < Priority; end
+ #
+ # @low = Priority.build(:low)
+ # @medium = Priority.build(:medium)
+ # @high = Priority.build(:high)
+ # priorities = [@low, @high, @medium]
+ # priorities.sort # => [@low, @medium, @high]
+ # priorities.max # => @high
+ # priorities.min # => @low
+ def <=> other
+ index <=> other.index
+ end
+
+ def self.included(klass)
+ klass.extend ClassMethods
+ end
+
+ module ClassMethods
+ def inherited(klass)
+ if self == ClassyEnum::Base
+ klass.class_attribute :enum_options
+ klass.enum_options = []
+ else
+ enum_options << klass
+ klass.instance_variable_set('@index', enum_options.size)
+ end
+
+ super
+ end
+
+ # Returns an array of all instantiated enums
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::Medium < Priority; end
+ # class Priority::High < Priority; end
+ #
+ # Priority.all # => [Priority::Low.new, Priority::Medium.new, Priority::High.new]
+ def all
+ enum_options.map(&:new)
+ end
+
+ # Returns a 2D array for Rails select helper options.
+ # Also used internally for Formtastic support
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::ReallyHigh < Priority; end
+ #
+ # Priority.select_options # => [["Low", "low"], ["Really High", "really_high"]]
+ def select_options
+ all.map {|e| [e.to_s.titleize, e.to_s] }
+ end
+ end
+
+ end
+end
View
69 lib/classy_enum/conversion.rb
@@ -0,0 +1,69 @@
+module ClassyEnum
+ module Conversion
+
+ # Returns an integer representing the order that this element was defined in.
+ # Also used internally for sorting.
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::Medium < Priority; end
+ # class Priority::High < Priority; end
+ #
+ # @priority = Priority::Medium.new
+ # @priority.to_i # => 2
+ def to_i
+ self.class.instance_variable_get('@index')
+ end
+
+ alias :index :to_i
+
+ # Returns the name or string corresponding to element
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::Medium < Priority; end
+ # class Priority::High < Priority; end
+ #
+ # @priority = Priority::Low.new
+ # @priority.to_s # => 'low'
+ def to_s
+ self.class.instance_variable_get('@option').to_s
+ end
+
+ # Returns a Symbol corresponding to a string representation of element,
+ # creating the symbol if it did not previously exist
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Priority < ClassyEnum::Base
+ # end
+ #
+ # class Priority::Low < Priority; end
+ # class Priority::Medium < Priority; end
+ # class Priority::High < Priority; end
+ #
+ # @priority = Priority::Low.new
+ # @priority.to_sym # => :low
+ def to_sym
+ to_s.to_sym
+ end
+
+ # Overrides as_json to remove owner reference recursion issues
+ def as_json(options=nil)
+ return to_s unless serialize_as_json
+ json = super(options)
+ json.delete('owner')
+ json.delete('serialize_as_json')
+ json
+ end
+
+ end
+end
View
122 lib/classy_enum/instance_methods.rb
@@ -1,122 +0,0 @@
-module ClassyEnum
- module InstanceMethods
- # Returns an integer representing the order that this element was defined in.
- # Also used internally for sorting.
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # @priority = PriorityMedium.new
- # @priority.index # => 2
- def index
- self.class.instance_variable_get('@index')
- end
-
- alias :to_i :index
-
- # Returns the name or string corresponding to element
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # @priority = PriorityLow.new
- # @priority.to_s # => 'low'
- def to_s
- self.class.instance_variable_get('@option').to_s
- end
-
- # Returns a Symbol corresponding to a string representation of element,
- # creating the symbol if it did not previously exist
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # @priority = PriorityLow.new
- # @priority.to_sym # => :low
- def to_sym
- to_s.to_sym
- end
-
- # Returns string representing enum in Rails titleize format
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high, :really_high
- # end
- #
- # @priority = Priority.build(:really_high)
- # @priority.name # => "Really High"
- def name
- ActiveSupport::Deprecation.warn('name is deprecated, and will be removed in ClassyEnum 3.0. Replace calls with to_s.titleize.', caller)
- to_s.titleize
- end
-
- # Sort an array of elements based on the order they are defined
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Priority < ClassyEnum::Base
- # enum_classes :low, :medium, :high
- # end
- #
- # @low = Priority.build(:low)
- # @medium = Priority.build(:medium)
- # @high = Priority.build(:high)
- # priorities = [@low, @high, @medium]
- # priorities.sort # => [@low, @medium, @high]
- # priorities.max # => @high
- # priorities.min # => @low
- def <=> other
- index <=> other.index
- end
-
- # Overrides as_json to remove owner reference recursion issues
- def as_json(options=nil)
- return to_s unless serialize_as_json
- json = super(options)
- json.delete('owner')
- json.delete('serialize_as_json')
- json
- end
-
- protected
-
- # Determine if the enum attribute is a particular member.
- #
- # ==== Example
- # # Create an Enum with some elements
- # class Breed < ClassyEnum::Base
- # enum_classes :golden_retriever, :snoop
- # end
- #
- # # Create an ActiveRecord class using the Breed enum
- # class Dog < ActiveRecord::Base
- # classy_enum_attr :breed
- # end
- #
- # @dog = Dog.new(:breed => :snoop)
- # @dog.breed.snoop? # => true
- # @dog.breed.golden_retriever? # => false
- def attribute?(attribute)
- to_s == attribute
- end
-
- private
-
- # Used by attribute methods
- def attributes
- []
- end
-
- end
-end
View
35 lib/classy_enum/predicate.rb
@@ -0,0 +1,35 @@
+module ClassyEnum
+ module Predicate
+
+ # Define attribute methods like two?
+ def self.define_predicate_method(klass, enum)
+ klass.base_class.class_eval do
+ define_method "#{enum}?", lambda { attribute?(enum.to_s) }
+ end
+ end
+
+ protected
+
+ # Determine if the enum attribute is a particular member.
+ #
+ # ==== Example
+ # # Create an Enum with some elements
+ # class Breed < ClassyEnum::Base
+ # end
+ #
+ # class Breed::GoldenRetriever < Breed; end
+ # class Breed::Snoop < Breed; end
+ #
+ # # Create an ActiveRecord class using the Breed enum
+ # class Dog < ActiveRecord::Base
+ # classy_enum_attr :breed
+ # end
+ #
+ # @dog = Dog.new(:breed => :snoop)
+ # @dog.breed.snoop? # => true
+ # @dog.breed.golden_retriever? # => false
+ def attribute?(attribute)
+ to_s == attribute
+ end
+ end
+end
View
2 lib/classy_enum/version.rb
@@ -1,3 +1,3 @@
module ClassyEnum
- VERSION = "2.3.0"
+ VERSION = "3.0.0"
end
View
1 lib/generators/classy_enum/templates/enum.rb
@@ -1,5 +1,4 @@
class <%= class_name %> < ClassyEnum::Base
- enum_classes <%= values.map {|a| ":#{a}"}.join(", ") %>
end
<% values.each do |arg| %>
class <%= "#{class_name}::#{arg.camelize}" %> < <%= class_name %>
View
70 spec/active_record_spec.rb
@@ -1,70 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-
-class Color < ClassyEnum::Base
- enum_classes :white, :black
-end
-
-class ColorWhite < Color; end;
-
-class ColorBlack < Color; end;
-
-class ActiveDog < ActiveRecord::Base
- classy_enum_attr :breed, :suffix => 'type'
- classy_enum_attr :color
-
- validates :name,
- :presence => true,
- :uniqueness => { :scope => [:breed] }
-
- validates_uniqueness_of :name, :scope => :color
-
- scope :goldens, where(:breed => 'golden_retriever')
-
-end
-
-describe ActiveDog do
-
- context 'valid instance' do
- subject { ActiveDog.new(:name => 'sirius', :breed => :golden_retriever, :color => :black) }
-
- it { should have(:no).errors_on(:breed) }
- its(:breed_type) { should be_a_golden_retriever }
- its(:breed) { should == 'golden_retriever' }
- end
-
- context 'uniqueness on name' do
- subject { ActiveDog.new(:name => 'Kitteh', :breed => :golden_retriever, :color => :black) }
- it { should be_valid }
-
- context 'with existing kitteh' do
- before do
- ActiveDog.create!(:name => 'Kitteh', :breed => :husky, :color => :black)
- end
-
- it { should have(1).error_on(:name) }
- end
- end
-
- context 'invalid instance' do
- subject { ActiveDog.new(:name => 'sirius', :breed => :golden_retrievers, :color => :white) }
-
- it { should have(1).error_on(:breed) }
- end
-
- context 'scopes' do
- let!(:golden) { ActiveDog.create!(:name => 'Sebastian', :breed => :golden_retriever, :color => :white) }
- let!(:husky) { ActiveDog.create!(:name => 'Sirius', :breed => :husky, :color => :black) }
-
- after { ActiveDog.destroy_all }
-
- it 'should know all dogs' do
- ActiveDog.all.should include(golden, husky)
- end
-
- it 'should have a working scope' do
- ActiveDog.goldens.should include(golden)
- ActiveDog.goldens.should_not include(husky)
- end
- end
-
-end
View
156 spec/classy_enum/active_record_spec.rb
@@ -0,0 +1,156 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+class Breed < ClassyEnum::Base; end
+class Breed::GoldenRetriever < Breed; end
+class Breed::Snoop < Breed; end
+class Breed::Husky < Breed; end
+
+class Color < ClassyEnum::Base; end
+class Color::White < Color; end;
+class Color::Black < Color; end;
+
+class CatBreed < ClassyEnum::Base
+ owner :cat
+
+ def breed_color
+ "#{cat.color} #{self}"
+ end
+end
+
+class CatBreed::Abyssian < CatBreed; end
+class CatBreed::Bengal < CatBreed; end
+class CatBreed::Birman < CatBreed; end
+class CatBreed::Persian < CatBreed; end
+
+class Dog < ActiveRecord::Base
+ classy_enum_attr :breed
+end
+
+class AllowBlankBreedDog < ActiveRecord::Base
+ classy_enum_attr :breed, :allow_blank => true
+end
+
+class AllowNilBreedDog < ActiveRecord::Base
+ classy_enum_attr :breed, :allow_nil => true
+end
+
+class OtherDog < ActiveRecord::Base
+ classy_enum_attr :other_breed, :enum => 'Breed'
+end
+
+describe Dog do
+ specify { Dog.new(:breed => nil).should_not be_valid }
+ specify { Dog.new(:breed => '').should_not be_valid }
+
+ context "with valid breed options" do
+ subject { Dog.new(:breed => :golden_retriever) }
+ it { should be_valid }
+ its(:breed) { should be_a(Breed::GoldenRetriever) }
+ its('breed.allow_blank') { should be_false }
+ end
+
+ context "with invalid breed options" do
+ subject { Dog.new(:breed => :fake_breed) }
+ it { should_not be_valid }
+ it { should have(1).error_on(:breed) }
+ end
+end
+
+describe "A ClassyEnum that allows blanks" do
+ specify { AllowBlankBreedDog.new(:breed => nil).should be_valid }
+ specify { AllowBlankBreedDog.new(:breed => '').should be_valid }
+
+ context "with valid breed options" do
+ subject { AllowBlankBreedDog.new(:breed => :golden_retriever) }
+ it { should be_valid }
+ its('breed.allow_blank') { should be_true }
+ end
+
+ context "with invalid breed options" do
+ subject { AllowBlankBreedDog.new(:breed => :fake_breed) }
+ it { should_not be_valid }
+ it { should have(1).error_on(:breed) }
+ end
+end
+
+describe "A ClassyEnum that allows nils" do
+ specify { AllowNilBreedDog.new(:breed => nil).should be_valid }
+ specify { AllowNilBreedDog.new(:breed => '').should_not be_valid }
+
+ context "with valid breed options" do
+ subject { AllowNilBreedDog.new(:breed => :golden_retriever) }
+ it { should be_valid }
+ its('breed.allow_blank') { should be_true }
+ end
+
+ context "with invalid breed options" do
+ subject { AllowNilBreedDog.new(:breed => :fake_breed) }
+ it { should_not be_valid }
+ it { should have(1).error_on(:breed) }
+ end
+end
+
+describe "A ClassyEnum that has a different field name than the enum" do
+ subject { OtherDog.new(:other_breed => :snoop) }
+ its(:other_breed) { should be_a(Breed::Snoop) }
+end
+
+class ActiveDog < ActiveRecord::Base
+ classy_enum_attr :color
+ validates_uniqueness_of :name, :scope => :color
+ scope :goldens, where(:breed => 'golden_retriever')
+end
+
+describe ActiveDog do
+ context 'uniqueness on name' do
+ subject { ActiveDog.new(:name => 'Kitteh', :breed => :golden_retriever, :color => :black) }
+ it { should be_valid }
+
+ context 'with existing kitteh' do
+ before do
+ ActiveDog.create!(:name => 'Kitteh', :breed => :husky, :color => :black)
+ end
+
+ it { should have(1).error_on(:name) }
+ end
+ end
+
+ context 'scopes' do
+ let!(:golden) { ActiveDog.create!(:name => 'Sebastian', :breed => :golden_retriever, :color => :white) }
+ let!(:husky) { ActiveDog.create!(:name => 'Sirius', :breed => :husky, :color => :black) }
+
+ after { ActiveDog.destroy_all }
+
+ it 'should know all dogs' do
+ ActiveDog.all.should include(golden, husky)
+ end
+
+ it 'should have a working scope' do
+ ActiveDog.goldens.should include(golden)
+ ActiveDog.goldens.should_not include(husky)
+ end
+ end
+
+end
+
+class Cat < ActiveRecord::Base
+ classy_enum_attr :breed, :enum => 'CatBreed'
+ attr_accessor :color
+ delegate :breed_color, :to => :breed
+end
+
+class OtherCat < ActiveRecord::Base
+ classy_enum_attr :breed, :enum => 'CatBreed', :serialize_as_json => true
+ attr_accessor :color
+ delegate :breed_color, :to => :breed
+end
+
+describe Cat do
+ let(:abyssian) { Cat.new(:breed => :abyssian, :color => 'black') }
+ let(:persian) { OtherCat.new(:breed => :persian, :color => 'white') }
+
+ it 'should delegate breed color to breed with an ownership reference' do
+ abyssian.breed_color { should eql('black Abyssian') }
+ persian.breed_color { should eql('white Persian') }
+ end
+end
View
50 spec/classy_enum/base_spec.rb
@@ -0,0 +1,50 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+class ClassyEnumBase < ClassyEnum::Base
+end
+
+class ClassyEnumBase::One < ClassyEnumBase
+end
+
+class ClassyEnumBase::Two < ClassyEnumBase
+end
+
+describe ClassyEnum::Base do
+ context '.build' do
+ context 'invalid option' do
+ it 'should return the option' do
+ ClassyEnumBase.build(:invalid_option).should == :invalid_option
+ end
+ end
+
+ context 'string option' do
+ subject { ClassyEnumBase.build("one") }
+ it { should be_a(ClassyEnumBase::One) }
+ end
+
+ context 'symbol option' do
+ subject { ClassyEnumBase.build(:two) }
+ it { should be_a(ClassyEnumBase::Two) }
+ end
+ end
+
+ context '#new' do
+ subject { ClassyEnumBase::One }
+ its(:new) { should be_a(ClassyEnumBase::One) }
+ its(:new) { should == ClassyEnumBase::One.new }
+ end
+
+ context 'Subclass naming' do
+ it 'should raise an error when invalid' do
+ lambda {
+ class WrongSublcassName < ClassyEnumBase; end
+ }.should raise_error(ClassyEnum::SubclassNameError)
+ end
+ end
+end
+
+describe ClassyEnum::Base, 'Arel visitor' do
+ specify do
+ Arel::Visitors::ToSql.instance_methods.map(&:to_sym).should include(:'visit_ClassyEnumBase_One', :'visit_ClassyEnumBase_Two')
+ end
+end
View
32 spec/classy_enum/collection_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+class ClassyEnumCollection < ClassyEnum::Base
+end
+
+class ClassyEnumCollection::One < ClassyEnumCollection
+end
+
+class ClassyEnumCollection::Two < ClassyEnumCollection
+end
+
+class ClassyEnumCollection::Three < ClassyEnumCollection
+end
+
+describe ClassyEnum::Collection do
+ subject { ClassyEnumCollection }
+
+ its(:enum_options) { should == [ClassyEnumCollection::One, ClassyEnumCollection::Two, ClassyEnumCollection::Three] }
+ its(:all) { should == [ClassyEnumCollection::One.new, ClassyEnumCollection::Two.new, ClassyEnumCollection::Three.new] }
+ its(:select_options) { should == [['One', 'one'],['Two', 'two'], ['Three', 'three']] }
+end
+
+describe ClassyEnum::Collection, Comparable do
+ let(:one) { ClassyEnumCollection::One.new }
+ let(:two) { ClassyEnumCollection::Two.new }
+ let(:three) { ClassyEnumCollection::Three.new }
+
+ subject { [one, three, two] }
+ its(:sort) { should eql([one, two, three]) }
+ its(:max) { should eql(three) }
+ its(:min) { should eql(one) }
+end
View
55 spec/classy_enum/conversion_spec.rb
@@ -0,0 +1,55 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+class ClassyEnumConversion < ClassyEnum::Base
+end
+
+class ClassyEnumConversion::One < ClassyEnumConversion
+end
+
+class ClassyEnumConversion::Two < ClassyEnumConversion
+end
+
+describe ClassyEnum::Conversion do
+ context '#to_i' do
+ specify { ClassyEnumConversion::One.new.to_i.should == 1 }
+ specify { ClassyEnumConversion::Two.new.to_i.should == 2 }
+ end
+
+ context '#index' do
+ specify { ClassyEnumConversion::One.new.index.should == 1 }
+ specify { ClassyEnumConversion::Two.new.index.should == 2 }
+ end
+
+ context '#to_s' do
+ specify { ClassyEnumConversion::One.new.to_s.should == 'one' }
+ specify { ClassyEnumConversion::Two.new.to_s.should == 'two' }
+ end
+
+ context '#to_sym' do
+ specify { ClassyEnumConversion::One.new.to_sym.should == :one }
+ specify { ClassyEnumConversion::Two.new.to_sym.should == :two }
+ end
+
+ context '#as_json' do
+ context 'serialize_as_json is false' do
+ specify { ClassyEnumConversion::One.new.as_json.should == 'one' }
+ specify { ClassyEnumConversion::Two.new.as_json.should == 'two' }
+ end
+
+ context 'serialize_as_json is true' do
+ specify do
+ enum = ClassyEnumConversion::One.new
+ enum.serialize_as_json = true
+ enum.instance_variable_set('@key', 'value')
+ enum.as_json.should == {'key' => 'value' }
+ end
+
+ specify do
+ enum = ClassyEnumConversion::One.new
+ enum.serialize_as_json = true
+ enum.instance_variable_set('@key', 'value')
+ enum.as_json.should == {'key' => 'value' }
+ end
+ end
+ end
+end
View
19 spec/classy_enum/predicate_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+class ClassyEnumPredicate < ClassyEnum::Base
+end
+
+class ClassyEnumPredicate::One < ClassyEnumPredicate
+end
+
+class ClassyEnumPredicate::Two < ClassyEnumPredicate
+end
+
+describe ClassyEnum::Predicate do
+ context '#attribute?' do
+ specify { ClassyEnumPredicate::One.new.should be_one }
+ specify { ClassyEnumPredicate::One.new.should_not be_two }
+ specify { ClassyEnumPredicate::Two.new.should_not be_one }
+ specify { ClassyEnumPredicate::Two.new.should be_two }
+ end
+end
View
97 spec/classy_enum_attributes_spec.rb
@@ -1,97 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-
-describe "A Dog" do
-
- context "with valid breed options" do
- subject { Dog.new(:breed => :golden_retriever) }
-
- it { should be_valid }
- its(:breed) { should be_a(BreedGoldenRetriever) }
- its(:breed_options) { should eql({:enum => :breed, :allow_blank => false}) }
- end
-
- it "should not be valid with a nil breed" do
- Dog.new(:breed => nil).should_not be_valid
- end
-
- it "should not be valid with a blank breed" do
- Dog.new(:breed => "").should_not be_valid
- end
-
- context "with invalid breed options" do
- let(:dog) { Dog.new(:breed => :fake_breed) }
- subject { dog }
- it { should_not be_valid }
-
- it 'should have an error message containing the right options' do
- dog.valid?
- dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
- end
- end
-
-end
-
-describe "A ClassyEnum that allows blanks" do
-
- context "with valid breed options" do
- subject { AllowBlankBreedDog.new(:breed => :golden_retriever) }
-
- it { should be_valid }
- its(:breed_options) { should eql({:enum => :breed, :allow_blank => true}) }
- end
-
- it "should be valid with a nil breed" do
- AllowBlankBreedDog.new(:breed => nil).should be_valid
- end
-
- it "should be valid with a blank breed" do
- AllowBlankBreedDog.new(:breed => "").should be_valid
- end
-
- context "with invalid breed options" do
- let(:dog) { AllowBlankBreedDog.new(:breed => :fake_breed) }
- subject { dog }
- it { should_not be_valid }
-
- it 'should have an error message containing the right options' do
- dog.valid?
- dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
- end
- end
-
-end
-
-describe "A ClassyEnum that allows nils" do
-
- context "with valid breed options" do
- subject { AllowNilBreedDog.new(:breed => :golden_retriever) }
-
- it { should be_valid }
- its(:breed_options) { should eql({:enum => :breed, :allow_blank => false}) }
- end
-
- it "should be valid with a nil breed" do
- AllowNilBreedDog.new(:breed => nil).should be_valid
- end
-
- it "should not be valid with a blank breed" do
- AllowNilBreedDog.new(:breed => "").should_not be_valid
- end
-
- context "with invalid breed options" do
- let(:dog) { AllowNilBreedDog.new(:breed => :fake_breed) }
- subject { dog }
- it { should_not be_valid }
-
- it 'should have an error message containing the right options' do
- dog.valid?
- dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
- end
- end
-
-end
-
-describe "A ClassyEnum that has a different field name than the enum" do
- subject { OtherDog.new(:other_breed => :snoop) }
- its(:other_breed) { should be_a(BreedSnoop) }
-end
View
28 spec/classy_enum_inheritance_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+class ProjectTier < ClassyEnum::Base
+ class_attribute :inherited_properties
+end
+
+class ProjectTier::One < ProjectTier
+ self.inherited_properties = [1,2,3]
+end
+
+class ProjectTier::Two < ProjectTier::One
+ self.inherited_properties += [4,5,6]
+end
+
+describe 'Classy Enum inheritance' do
+ it 'should inherit from the previous class' do
+ ProjectTier::One.inherited_properties.should == [1,2,3]
+ ProjectTier::Two.inherited_properties.should == [1,2,3,4,5,6]
+ end
+
+ it 'should instantiate the subclass' do
+ ProjectTier::Two.build(:two).should == ProjectTier::Two.new
+ end
+
+ it 'should have the right index' do
+ ProjectTier::Two.new.index.should == 2
+ end
+end
View
53 spec/classy_enum_owner_reference_spec.rb
@@ -1,53 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-
-class CatBreed < ClassyEnum::Base
- enum_classes :abyssian, :bengal, :birman, :persian
- owner :cat
-
- def breed_color
- "#{cat.color} #{name}"
- end
-end
-
-class CatBreedAbyssian < CatBreed
-end
-
-class CatBreedBengal < CatBreed
-end
-
-class CatBreedBirman < CatBreed
-end
-
-class CatBreedPersian < CatBreed
-end
-
-class Cat < ActiveRecord::Base
- classy_enum_attr :breed, :enum => :cat_breed
- attr_accessor :color
- delegate :breed_color, :to => :breed
-end
-
-class OtherCat < ActiveRecord::Base
- classy_enum_attr :breed, :enum => :cat_breed, :serialize_as_json => true
- attr_accessor :color
- delegate :breed_color, :to => :breed
-end
-
-describe Cat do
- let(:abyssian) { Cat.new(:breed => :abyssian, :color => 'black') }
- let(:persian) { OtherCat.new(:breed => :persian, :color => 'white') }
-
- it 'should delegate breed color to breed with an ownership reference' do
- abyssian.breed_color { should eql('black Abyssian') }
- persian.breed_color { should eql('white Persian') }
- end
-
- it 'should correctly serialize without the owner reference' do
- JSON.parse(abyssian.to_json)['cat']['breed'].should == 'abyssian'
- end
-
- it 'should convert the enum to a string when serializing' do
- JSON.parse(persian.to_json)['other_cat']['breed'].should be_a(Hash)
- end
-
-end
View
105 spec/classy_enum_spec.rb
@@ -1,105 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-
-class TestEnum < ClassyEnum::Base
- enum_classes :one, :two, :three
-
- def self.test_class_method?
- false
- end
-
- def test_instance_method?
- false
- end
-end
-
-class TestEnumOne < TestEnum
-end
-
-class TestEnumTwo < TestEnum
- def self.test_class_method?
- true
- end
-
- def test_instance_method?
- true
- end
-end
-
-class TestEnumThree < TestEnum
-end
-
-describe "A ClassyEnum Descendent" do
-
- it "should return an array of enums" do
- TestEnum.all.map(&:class).should == [TestEnumOne, TestEnumTwo, TestEnumThree]
- end
-
- it "should return an array of enums for a select tag" do
- TestEnum.select_options.should == TestEnum.enum_options.map {|o| [TestEnum.build(o).name, TestEnum.build(o).to_s] }
- end
-
- it "should return a type error when adding an invalid option" do
- TestEnum.build(:invalid_option).class.should == TypeError
- end
-
- it "should find an enum by symbol" do
- TestEnum.find(:one).class.should == TestEnumOne
- end
-
- it "should find an enum by string" do
- TestEnum.find("one").class.should == TestEnumOne
- end
-
- it "should create an instance with a string" do
- TestEnum.build("one").should be_a(TestEnumOne)
- end
-end
-
-describe "A collection of ClassyEnums" do
- let(:one) { TestEnum.build(:one) }
- let(:two) { TestEnum.build(:two) }
- let(:three) { TestEnum.build(:three) }
-
- subject { [one, three, two] }
- its(:sort) { should eql([one, two, three]) }
- its(:max) { should eql(three) }
-end
-
-describe "A ClassyEnum element" do
- it "should instantiate a member" do
- TestEnumOne.new.should be_a(TestEnumOne)
- end
-
- it "should inherit the default class methods" do
- TestEnumOne.test_class_method?.should be_false
- end
-
- it "should compare different elements based on their index" do
- TestEnumOne.new.should == TestEnumOne.new
- end
-end
-
-describe "A ClassyEnum instance" do
- subject { TestEnum.build(:one) }
-
- it { should be_a(TestEnum) }
- its(:class) { should eql(TestEnumOne) }
- its(:one?) { should be_true }
- its(:two?) { should be_false }
- its(:index) { should eql(1) }
- its(:to_i) { should eql(1) }
- its(:to_s) { should eql('one') }
- its(:to_sym) { should be(:one) }
- its(:name) { should eql('One') }
- its(:test_instance_method?) { should be_false }
-end
-
-describe "A ClassyEnum that overrides values" do
- subject { TestEnum.build(:two) }
-
- its(:test_instance_method?) { should be_true }
-
- it "should override the default class methods" do
- TestEnumTwo.test_class_method?.should be_true
- end
-end
View
29 spec/spec_helper.rb
@@ -46,32 +46,3 @@
t.string :breed
end
end
-
-class Breed < ClassyEnum::Base
- enum_classes :golden_retriever, :snoop, :husky
-end
-
-class BreedGoldenRetriever < Breed
-end
-
-class BreedSnoop < Breed
-end
-
-class BreedHusky < Breed
-end
-
-class Dog < ActiveRecord::Base
- classy_enum_attr :breed
-end
-
-class AllowBlankBreedDog < ActiveRecord::Base
- classy_enum_attr :breed, :allow_blank => true
-end
-
-class AllowNilBreedDog < ActiveRecord::Base
- classy_enum_attr :breed, :allow_nil => true
-end
-
-class OtherDog < ActiveRecord::Base
- classy_enum_attr :other_breed, :enum => :breed
-end

0 comments on commit 16ed8da

Please sign in to comment.
Something went wrong with that request. Please try again.