Skip to content

Commit

Permalink
Moving enum options from model to enum member
Browse files Browse the repository at this point in the history
  • Loading branch information
beerlington committed Jul 19, 2012
1 parent 7d6d8da commit fb7c660
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 41 deletions.
15 changes: 7 additions & 8 deletions lib/classy_enum/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,29 @@ def classy_enum_attr(*args)
reader_method += "_#{options[:suffix]}" if options.has_key?(:suffix)

valid_attributes = reader_method == attribute.to_s ? enum.all : enum.all.map(&:to_s)
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 => valid_attributes,
:message => enum.invalid_message,
:message => error_message,
:allow_blank => allow_blank,
:allow_nil => allow_nil

# Define getter method that returns a ClassyEnum instance
define_method reader_method do
enum.build(read_attribute(attribute), :owner => self, :serialize_as_json => serialize_as_json)
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

# 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
Expand Down
33 changes: 9 additions & 24 deletions lib/classy_enum/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Base
include Collection

class_attribute :base_class
attr_accessor :owner, :serialize_as_json
attr_accessor :owner, :serialize_as_json, :allow_blank

class << self
def inherited(klass)
Expand Down Expand Up @@ -37,7 +37,8 @@ def inherited(klass)
super
end

# Build a new ClassyEnum child instance
# 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
Expand All @@ -48,36 +49,20 @@ def inherited(klass)
# end
#
# Priority.build(:low) # => Priority::Low.new
# Priority.build(:invalid_option) # => :invalid_option
def build(value, options={})
return value if value.blank?
return value if value.blank? && options[:allow_blank]

# Return a TypeError if the build value is not a valid member
unless all.map(&:to_sym).include? value.to_sym
return TypeError.new("#{base_class} #{invalid_message}")
end
# 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 = "#{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

# Returns a a message indicating which fields are valid
#
# ==== 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
#
# Priortiy.invalid_message # => must be low, medium, or high
def invalid_message
"must be #{all.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ')}"
end

# DSL setter method for overriding reference to enum owner (ActiveRecord model)
#
# ==== Example
Expand Down
6 changes: 3 additions & 3 deletions spec/classy_enum/active_record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class OtherDog < ActiveRecord::Base
subject { Dog.new(:breed => :golden_retriever) }
it { should be_valid }
its(:breed) { should be_a(Breed::GoldenRetriever) }
its(:breed_options) { should == {:enum => Breed, :allow_blank => false} }
its('breed.allow_blank') { should be_false }
end

context "with invalid breed options" do
Expand All @@ -63,7 +63,7 @@ class OtherDog < ActiveRecord::Base
context "with valid breed options" do
subject { AllowBlankBreedDog.new(:breed => :golden_retriever) }
it { should be_valid }
its(:breed_options) { should == {:enum => Breed, :allow_blank => true} }
its('breed.allow_blank') { should be_true }
end

context "with invalid breed options" do
Expand All @@ -80,7 +80,7 @@ class OtherDog < ActiveRecord::Base
context "with valid breed options" do
subject { AllowNilBreedDog.new(:breed => :golden_retriever) }
it { should be_valid }
its(:breed_options) { should == {:enum => Breed, :allow_blank => false} }
its('breed.allow_blank') { should be_true }
end

context "with invalid breed options" do
Expand Down
9 changes: 3 additions & 6 deletions spec/classy_enum/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ class ClassyEnumBase::Two < ClassyEnumBase
describe ClassyEnum::Base do
context '.build' do
context 'invalid option' do
subject { ClassyEnumBase.build(:invalid_option) }
its(:class) { should == TypeError }
it 'should return the option' do
ClassyEnumBase.build(:invalid_option).should == :invalid_option
end
end

context 'string option' do
Expand All @@ -27,10 +28,6 @@ class ClassyEnumBase::Two < ClassyEnumBase
end
end

context '.invalid_message' do
ClassyEnumBase.invalid_message.should == 'must be one or two'
end

context '#new' do
subject { ClassyEnumBase::One }
its(:new) { should be_a(ClassyEnumBase::One) }
Expand Down

0 comments on commit fb7c660

Please sign in to comment.