diff --git a/lib/mongoid/enum.rb b/lib/mongoid/enum.rb index 19b78b1..20dc37e 100644 --- a/lib/mongoid/enum.rb +++ b/lib/mongoid/enum.rb @@ -14,10 +14,10 @@ module Mongoid set_values_constant name, values create_field field_name, options - alias_attribute name, field_name create_validations field_name, values, options define_value_scopes_and_accessors field_name, values, options + define_field_accessor name, field_name, options end private @@ -42,9 +42,10 @@ module Mongoid def create_validations(field_name, values, options) if options[:multiple] && options[:validate] - validates field_name, :'mongoid/enum/validators/multiple' => { :in => values, :allow_nil => !options[:required] } + validates field_name, :'mongoid/enum/validators/multiple' => { :in => values.map(&:to_sym), :allow_nil => !options[:required] } + #FIXME: Shouldn't this be `elsif options[:validate]` ??? elsif validate - validates field_name, :inclusion => {:in => values}, :allow_nil => !options[:required] + validates field_name, :inclusion => {:in => values.map(&:to_sym)}, :allow_nil => !options[:required] end end @@ -60,6 +61,24 @@ module Mongoid end end + def define_field_accessor(name, field_name, options) + if options[:multiple] + define_array_field_accessor name, field_name + else + define_string_field_accessor name, field_name + end + end + + def define_array_field_accessor(name, field_name) + class_eval "def #{name}=(vals) self.write_attribute(:#{field_name}, Array(vals).compact.map(&:to_sym)) end" + class_eval "def #{name}() self.read_attribute(:#{field_name}) end" + end + + def define_string_field_accessor(name, field_name) + class_eval "def #{name}=(val) self.write_attribute(:#{field_name}, val && val.to_sym || nil) end" + class_eval "def #{name}() self.read_attribute(:#{field_name}) end" + end + def define_array_accessor(field_name, value) class_eval "def #{value}?() self.#{field_name}.include?(:#{value}) end" class_eval "def #{value}!() update_attributes! :#{field_name} => (self.#{field_name} || []) + [:#{value}] end" diff --git a/spec/mongoid/enum_spec.rb b/spec/mongoid/enum_spec.rb index 4139e1d..5bd9c3c 100644 --- a/spec/mongoid/enum_spec.rb +++ b/spec/mongoid/enum_spec.rb @@ -42,7 +42,7 @@ describe Mongoid::Enum do it "is aliased" do expect(instance).to respond_to alias_name expect(instance).to respond_to :"#{alias_name}=" - expect(instance).to respond_to :"#{alias_name}?" + expect(instance).to respond_to :"#{alias_name}" end describe "type" do @@ -92,6 +92,18 @@ describe Mongoid::Enum do describe "accessors" do context "when singular" do + describe "setter" do + it "accepts strings" do + instance.status = 'banned' + expect(instance.status).to eq :banned + end + + it "accepts symbols" do + instance.status = :banned + expect(instance.status).to eq :banned + end + end + describe "{{value}}!" do it "sets the value" do instance.save @@ -119,6 +131,33 @@ describe Mongoid::Enum do end context "when multiple" do + describe "setter" do + it "accepts strings" do + instance.roles = "author" + expect(instance.roles).to eq [:author] + end + + it "accepts symbols" do + instance.roles = :author + expect(instance.roles).to eq [:author] + end + + it "accepts arrays of strings" do + instance.roles = ['author', 'editor'] + instance.save + puts instance.errors.full_messages + instance.reload + expect(instance.roles).to include(:author) + expect(instance.roles).to include(:editor) + end + + it "accepts arrays of symbols" do + instance.roles = [:author, :editor] + expect(instance.roles).to include(:author) + expect(instance.roles).to include(:editor) + end + end + describe "{{value}}!" do context "when field is nil" do it "creates an array containing the value" do