Permalink
Browse files

better macro support

  • Loading branch information...
1 parent aad8029 commit ef583c89aab6b812f6e36f693ca15fc47d07face @kristianmandrup committed Aug 6, 2012
View
@@ -1,5 +1,6 @@
require 'classy_enum/collection'
require 'classy_enum/conversion'
require 'classy_enum/predicate'
+require 'classy_enum/valid_values'
require 'classy_enum/base'
require 'classy_enum/active_record'
View
@@ -11,16 +11,25 @@ class Base
attr_accessor :owner, :serialize_as_json, :allow_blank
class << self
+ def valid? value
+ valid_values.include? value.to_sym
+ end
+
+ def valid_values
+ @valid_values ||= []
+ end
+
def inherited(klass)
if self == ClassyEnum::Base
klass.base_class = klass
+ klass.send :include, ClassyEnum::ValidValues
else
return unless klass.name
# 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
+ 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
@@ -35,6 +44,8 @@ def inherited(klass)
# Convert from MyEnumClass::NumberTwo to :number_two
enum = klass.name.split('::').last.underscore.to_sym
+ base_class.valid_values << enum
+
Predicate.define_predicate_method(klass, enum)
klass.instance_variable_set('@option', enum)
@@ -86,6 +97,5 @@ def owner(owner)
define_method owner, lambda { @owner }
end
end
-
end
end
View
@@ -1,9 +1,16 @@
def enum name, parent_class = nil, &block
- clazz_name = name.to_s.camelize
- context = self.inspect == 'main' ? Object : self
- parent_class ||= context unless context == Object
+ clazz_name = name.to_s.camelize
+ if parent_class != :no_context
+ context = self.inspect == 'main' ? Object : self
+ parent_class ||= context unless context == Object
+ else
+ context = Object
+ parent_class = nil
+ end
parent_class ||= ::ClassyEnum::Base
+ raise "Bad superclass: #{parent_class}" unless parent_class.kind_of?(Class)
+
klass = Class.new(parent_class)
context.const_set clazz_name, klass
@@ -31,7 +38,8 @@ def enum name, parent_class = nil, &block
end
# Convert from MyEnumClass::NumberTwo to :number_two
- enum = name
+ enum = name.to_sym
+ valid_values << enum
ClassyEnum::Predicate.define_predicate_method(klass, enum)
@@ -46,4 +54,10 @@ def enum name, parent_class = nil, &block
def enums *names
names.each {|name| enum name }
+end
+
+def enum_for name, list, options = {}
+ enum name, options[:parent] do
+ enums *list.flatten.compact
+ end
end
@@ -0,0 +1,11 @@
+module ClassyEnum
+ module ValidValues
+ def valid? value
+ self.base_class.valid? value
+ end
+
+ def valid_values
+ self.base_class.valid_values
+ end
+ end
+end
@@ -47,6 +47,10 @@ class OtherDog < ActiveRecord::Base
it { should be_valid }
its(:breed) { should be_a(Breed::GoldenRetriever) }
its('breed.allow_blank') { should be_false }
+
+ its('breed.valid_values') { should == [:golden_retriever, :snoop, :husky] }
+ specify { subject.breed.valid?(:snoop).should be_true }
+ specify { subject.breed.valid?(:snoop_dog).should be_false }
end
context "with invalid breed options" do
@@ -2,39 +2,67 @@
require 'classy_enum/macros'
-enum :priority do
- enum :one do
- def send_email?
- true
- end
- end
+describe 'ClassyEnum macros: #enum and #enums' do
+ before :all do
+ enum :number, :no_context do
+ enum :one do
+ def send_email?
+ true
+ end
+ end
- enums :two, :three
-end
+ enums :two, :three
+ end
+ end
-describe ClassyEnum::Base do
context '.build' do
context 'invalid option' do
it 'should return the option' do
- Priority.build(:invalid_option).should == :invalid_option
+ Number.build(:invalid_option).should == :invalid_option
end
end
context 'string option' do
- subject { Priority.build("one") }
- it { should be_a(::Priority::One) }
+ subject { Number.build("one") }
+ it { should be_a(::Number::One) }
end
context 'symbol option' do
describe 'two' do
- subject { Priority.build(:two) }
- it { should be_a(::Priority::Two) }
+ subject { Number.build(:two) }
+ it { should be_a(::Number::Two) }
end
describe 'three' do
- subject { Priority.build(:three) }
- it { should be_a(::Priority::Three) }
+ subject { Number.build(:three) }
+ it { should be_a(::Number::Three) }
+ end
+ end
+ end
+end
+
+describe 'ClassyEnum macros: #enum and #enums' do
+ before :all do
+ enum_for :color, [:red, :blue], parent: :no_context
+ end
+
+ context '.build' do
+ context 'invalid option' do
+ it 'should return the option' do
+ Color.build(:invalid_option).should == :invalid_option
+ end
+ end
+
+ context 'string option' do
+ subject { Color.build("red") }
+ it { should be_a(::Color::Red) }
+ end
+
+ context 'symbol option' do
+ describe 'two' do
+ subject { Color.build(:blue) }
+ it { should be_a(::Color::Blue) }
end
end
end
-end
+end

0 comments on commit ef583c8

Please sign in to comment.