Permalink
Browse files

Fixes an issue with select_options on nil/blank objects

This was a regression from 2.x where the ActiveRecord object was setting
enum options on itself. Because these options were no longer available,
there was no way to determine the associated enum if the value was nil
or blank. This introduces a sort of null object that is just a subclass
of the base enum that behaves like a nil or blank object.
  • Loading branch information...
1 parent db53df6 commit 29e4b895c9459c0c6c9e39636faaf4be5719353d @beerlington beerlington committed Aug 20, 2012
Showing with 41 additions and 5 deletions.
  1. +7 −0 CHANGELOG.md
  2. +11 −1 lib/classy_enum/base.rb
  3. +8 −3 lib/classy_enum/conversion.rb
  4. +1 −1 lib/classy_enum/version.rb
  5. +14 −0 spec/classy_enum/base_spec.rb
View
@@ -1,5 +1,12 @@
# ClassyEnum Changelog
+## 3.1.1
+
+* Fixes a regression with Formtastic support. ClassyEnumm::Base.build now
+ returns a null object that decends from the base_class when the argument is
+ blank (nil, empty string, etc). This allows the ActiveRecord model's enum
+ attribute to respond to enum methods even if it is blank.
+
## 3.1.0
* ClassyEnum::Base now extends Enumerable to provide enum collection
View
@@ -13,6 +13,8 @@ class Base
class << self
def inherited(klass)
+ return if klass.anonymous?
+
if self == ClassyEnum::Base
klass.base_class = klass
else
@@ -59,7 +61,15 @@ def inherited(klass)
def build(value, options={})
object = find(value)
- return value if object.nil? || (options[:allow_blank] && object.nil?)
+ if object.nil? || (options[:allow_blank] && object.nil?)
+ return value unless value.blank?
+
+ # Subclass the base class and make it behave like the value that it is
+ object = Class.new(base_class) {
+ instance_variable_set(:@option, value)
+ delegate :blank?, :nil?, :to => :option
+ }.new
+ end
object.owner = options[:owner]
object.serialize_as_json = options[:serialize_as_json]
@@ -28,14 +28,13 @@ def to_i
# class Priority < ClassyEnum::Base
# end
#
- # class Priority::Low < Priority; end
- # class Priority::Medium < Priority; 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
+ option.to_s
end
# Returns a Symbol corresponding to a string representation of element,
@@ -65,5 +64,11 @@ def as_json(options=nil)
json
end
+ private
+
+ def option
+ self.class.instance_variable_get(:@option)
+ end
+
end
end
@@ -1,3 +1,3 @@
module ClassyEnum
- VERSION = "3.1.0"
+ VERSION = "3.1.1"
end
@@ -26,6 +26,20 @@ class ClassyEnumBase::Two < ClassyEnumBase
subject { ClassyEnumBase.build(:two) }
it { should be_a(ClassyEnumBase::Two) }
end
+
+ context 'nil' do
+ subject { ClassyEnumBase.build(nil) }
+ it { should be_a(ClassyEnumBase) }
+ it { should be_nil }
+ it { should be_blank }
+ end
+
+ context 'empty string' do
+ subject { ClassyEnumBase.build('') }
+ it { should be_a(ClassyEnumBase) }
+ it { should_not be_nil }
+ it { should be_blank }
+ end
end
context '#new' do

0 comments on commit 29e4b89

Please sign in to comment.