Skip to content

Commit

Permalink
Merge branch 'enum'
Browse files Browse the repository at this point in the history
  • Loading branch information
benburkert committed Apr 19, 2008
2 parents 1312cc5 + 63274c2 commit b12527c
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lib/data_mapper.rb
Expand Up @@ -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)
Expand Down Expand Up @@ -92,4 +97,4 @@ def self.repository(name = :default) # :yields: current_context
end
end
end
end
end
37 changes: 37 additions & 0 deletions lib/data_mapper/types/enum.rb
@@ -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
48 changes: 48 additions & 0 deletions lib/data_mapper/types/flag.rb
@@ -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
63 changes: 63 additions & 0 deletions spec/types/enum_spec.rb
@@ -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
81 changes: 81 additions & 0 deletions spec/types/flag_spec.rb
@@ -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.