Permalink
Browse files

Merge branch 'enum'

  • Loading branch information...
2 parents 1312cc5 + 63274c2 commit b12527c8b88cb49c3ac4c5985f656a47e1b117a0 @benburkert benburkert committed Apr 19, 2008
Showing with 235 additions and 1 deletion.
  1. +6 −1 lib/data_mapper.rb
  2. +37 −0 lib/data_mapper/types/enum.rb
  3. +48 −0 lib/data_mapper/types/flag.rb
  4. +63 −0 spec/types/enum_spec.rb
  5. +81 −0 spec/types/flag_spec.rb
View
@@ -37,6 +37,11 @@
require __DIR__ + 'data_mapper/query'
require __DIR__ + 'data_mapper/adapters/abstract_adapter'
require __DIR__ + 'data_mapper/cli'
+require __DIR__ + 'data_mapper/scope'
+require __DIR__ + 'data_mapper/query'
+
+require __DIR__ + 'data_mapper/types/enum'
+require __DIR__ + 'data_mapper/types/flag'
module DataMapper
def self.setup(name, uri_or_options)
@@ -92,4 +97,4 @@ def self.repository(name = :default) # :yields: current_context
end
end
end
-end
+end
@@ -0,0 +1,37 @@
+module DataMapper
+ module Types
+ class Enum < DataMapper::Type(Fixnum)
+
+ def self.flag_map
+ @flag_map
+ end
+
+ def self.flag_map=(value)
+ @flag_map = value
+ end
+
+ def self.new(*flags)
+ enum = Enum.dup
+ enum.flag_map = {}
+
+ flags.each_with_index do |flag, i|
+ enum.flag_map[i + 1] = flag
+ end
+
+ enum
+ end
+
+ def self.[](*flags)
+ new(*flags)
+ end
+
+ def self.load(value)
+ self.flag_map[value]
+ end
+
+ def self.dump(flag)
+ self.flag_map.invert[flag]
+ end
+ end
+ end
+end
@@ -0,0 +1,48 @@
+module DataMapper
+ module Types
+ class Flag < DataMapper::Type(Fixnum)
+
+ def self.flag_map
+ @flag_map
+ end
+
+ def self.flag_map=(value)
+ @flag_map = value
+ end
+
+ def self.new(*flags)
+ type = Flag.dup
+ type.flag_map = {}
+
+ flags.each_with_index do |flag, i|
+ type.flag_map[2 ** i] = flag
+ end
+
+ type
+ end
+
+ def self.[](*flags)
+ new(*flags)
+ end
+
+ def self.load(value)
+ begin
+ matches = []
+
+ 0.upto((Math.log(value) / Math.log(2)).ceil) do |i|
+ pow = 2 ** i
+ matches << flag_map[pow] if value & pow == pow
+ end
+
+ matches.compact
+ rescue TypeError, Errno::EDOM
+ []
+ end
+ end
+
+ def self.dump(*flags)
+ flag_map.invert.values_at(*flags.flatten).compact.inject(0) {|sum, i| sum + i}
+ end
+ end
+ end
+end
View
@@ -0,0 +1,63 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+include DataMapper::Types
+
+describe DataMapper::Types::Enum do
+
+ describe ".new" do
+ it "should create a Class" do
+ Enum.new.should be_instance_of(Class)
+ end
+
+ it "should create unique a Class each call" do
+ Enum.new.should_not == Enum.new
+ end
+
+ it "should use the arguments as the values in the @flag_map hash" do
+ Enum.new(:first, :second, :third).flag_map.values.should == [:first, :second, :third]
+ end
+
+ it "should create incremental keys for the @flag_map hash, staring at 1" do
+ Enum.new(:one, :two, :three, :four).flag_map.keys.should == (1..4).to_a
+ end
+ end
+
+ describe ".[]" do
+ it "should be an alias for the new method" do
+ Enum.should_receive(:new).with(:uno, :dos, :tres)
+ Enum[:uno, :dos, :tres]
+ end
+ end
+
+ describe ".dump" do
+ before(:each) do
+ @enum = Enum[:first, :second, :third]
+ end
+
+ it "should return the key of the value match from the flag map" do
+ @enum.dump(:first).should == 1
+ @enum.dump(:second).should == 2
+ @enum.dump(:third).should == 3
+ end
+
+ it "should return nil if there is no match" do
+ @enum.dump(:zero).should be_nil
+ end
+ end
+
+ describe ".load" do
+ before(:each) do
+ @enum = Enum[:uno, :dos, :tres]
+ end
+
+ it "should return the value of the key match from the flag map" do
+ @enum.load(1).should == :uno
+ @enum.load(2).should == :dos
+ @enum.load(3).should == :tres
+ end
+
+ it "should return nil if there is no key" do
+ @enum.load(-1).should be_nil
+ end
+ end
+end
View
@@ -0,0 +1,81 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+include DataMapper::Types
+
+describe DataMapper::Types::Flag do
+
+ describe ".new" do
+ it "should create a Class" do
+ Flag.new.should be_instance_of(Class)
+ end
+
+ it "should create unique a Class each call" do
+ Flag.new.should_not == Flag.new
+ end
+
+ it "should use the arguments as the values in the @flag_map hash" do
+ Flag.new(:first, :second, :third).flag_map.values.should == [:first, :second, :third]
+ end
+
+ it "should create keys by the 2 power series for the @flag_map hash, staring at 1" do
+ Flag.new(:one, :two, :three, :four, :five).flag_map.keys.should include(1, 2, 4, 8, 16)
+ end
+ end
+
+ describe ".[]" do
+ it "should be an alias for the new method" do
+ Flag.should_receive(:new).with(:uno, :dos, :tres)
+ Flag[:uno, :dos, :tres]
+ end
+ end
+
+ describe ".dump" do
+ before(:each) do
+ @flag = Flag[:first, :second, :third, :fourth, :fifth]
+ end
+
+ it "should return the key of the value match from the flag map" do
+ @flag.dump(:first).should == 1
+ @flag.dump(:second).should == 2
+ @flag.dump(:third).should == 4
+ @flag.dump(:fourth).should == 8
+ @flag.dump(:fifth).should == 16
+ end
+
+ it "should return a binary flag built from the key values of all matches" do
+ @flag.dump(:first, :second).should == 3
+ @flag.dump(:second, :fourth).should == 10
+ @flag.dump(:first, :second, :third, :fourth, :fifth).should == 31
+ end
+
+ it "should return 0 if there is no match" do
+ @flag.dump(:zero).should == 0
+ end
+ end
+
+ describe ".load" do
+ before(:each) do
+ @flag = Flag[:uno, :dos, :tres, :cuatro, :cinco]
+ end
+
+ it "should return the value of the key match from the flag map" do
+ @flag.load(1).should == [:uno]
+ @flag.load(2).should == [:dos]
+ @flag.load(4).should == [:tres]
+ @flag.load(8).should == [:cuatro]
+ @flag.load(16).should == [:cinco]
+ end
+
+ it "should return an array of all flags matches" do
+ @flag.load(3).should include(:uno, :dos)
+ @flag.load(10).should include(:dos, :cuatro)
+ @flag.load(31).should include(:uno, :dos, :tres, :cuatro, :cinco)
+ end
+
+ it "should return an empty array if there is no key" do
+ @flag.load(-1).should == []
+ @flag.load(nil).should == []
+ @flag.load(32).should == []
+ end
+ end
+end

0 comments on commit b12527c

Please sign in to comment.