Permalink
Browse files

Add a bunch of specs for attribute type casting.

  • Loading branch information...
1 parent 83c27c0 commit 61916e408d86d19d1659cd8042de6503aecc6c98 Carl Lerche committed Mar 12, 2010
@@ -160,16 +160,13 @@ def type_cast(value)
def type_cast_to_numeric(value, method)
return unless value
if value.respond_to?(:to_str)
- if value.to_str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
- $1.send(method)
- else
- value
- end
+ str = value.to_str.strip
+ return if str.empty?
+ return $1.send(method) if str =~ /\A(-?(?:0|[1-9]\d*)(?:\.\d+)?|(?:\.\d+))\z/
elsif value.respond_to?(method)
- value.send(method)
- else
- raise typecast_error(value)
+ return value.send(method)
end
+ raise typecast_error(value)
end
def typecast_error(value)
@@ -3,11 +3,12 @@ module Attributes
class Boolean < Attribute
def type_cast(value)
case value
- when true, false then value
- when nil then options[:allow_nil] ? nil : false
- when 1 then true
- when 0 then false
- else
+ when true, false then value
+ # when nil then options[:allow_nil] ? nil : false
+ when nil then false
+ when 1 then true
+ when 0 then false
+ else
case value.to_s.downcase.strip
when 'true' then true
when 'false' then false
@@ -1,50 +1,5 @@
require 'spec_helper'
-module Arel
- module Testing
- class Engine
- attr_reader :rows
-
- def initialize
- @rows = []
- end
-
- def supports(operation)
- false
- end
-
- def read(relation)
- @rows.dup.map { |r| Row.new(relation, r) }
- end
-
- def create(insert)
- @rows << insert.record.tuple
- insert
- end
- end
- end
-end
-
-class Thing < Arel::Relation
- attr_reader :engine, :attributes
-
- def initialize(engine, attributes)
- @engine, @attributes = engine, []
- attributes.each do |name, type|
- @attributes << type.new(self, name)
- end
- end
-
- def format(attribute, value)
- value
- end
-
- def insert(row)
- insert = super Arel::Row.new(self, row)
- insert.record
- end
-end
-
def have_rows(expected)
simple_matcher "have rows" do |given, matcher|
found, got, expected = [], [], expected.map { |r| r.tuple }
@@ -101,11 +56,14 @@ module Arel
describe "Relation" do
before :all do
- @engine = Testing::Engine.new
- @relation = Thing.new(@engine,
- :id => Attributes::Integer,
- :name => Attributes::String,
- :age => Attributes::Integer)
+ @engine = Testing::Engine.new
+ @relation = Model.build do |r|
+ r.engine @engine
+
+ r.attribute :id, Attributes::Integer
+ r.attribute :name, Attributes::String
+ r.attribute :age, Attributes::Integer
+ end
end
describe "..." do
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+module Arel
+ describe "Attributes::Boolean" do
+
+ before :all do
+ @relation = Model.build do |r|
+ r.engine Testing::Engine.new
+ r.attribute :awesome, Attributes::Boolean
+ end
+ end
+
+ def type_cast(val)
+ @relation[:awesome].type_cast(val)
+ end
+
+ describe "#type_cast" do
+ it "returns same value if passed a boolean" do
+ val = true
+ type_cast(val).should eql(val)
+ end
+
+ it "returns boolean representation (false) of nil" do
+ type_cast(nil).should eql(false)
+ end
+
+ it "returns boolean representation of 'true', 'false'" do
+ type_cast('true').should eql(true)
+ type_cast('false').should eql(false)
+ end
+
+ it "returns boolean representation of :true, :false" do
+ type_cast(:true).should eql(true)
+ type_cast(:false).should eql(false)
+ end
+
+ it "returns boolean representation of 0, 1" do
+ type_cast(1).should == true
+ type_cast(0).should == false
+ end
+
+ it "calls #to_s on arbitrary objects" do
+ obj = Object.new
+ obj.extend Module.new { def to_s ; 'true' ; end }
+ type_cast(obj).should == true
+ end
+
+ [ Object.new, 'string', '00.0', 5 ].each do |value|
+ it "raises exception when attempting type_cast of non-boolean value #{value.inspect}" do
+ lambda do
+ type_cast(value)
+ end.should raise_error(TypecastError, /could not typecast/)
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,119 @@
+require 'spec_helper'
+require 'bigdecimal'
+
+module Arel
+ describe "Attributes::Float" do
+
+ before :all do
+ @relation = Model.build do |r|
+ r.engine Testing::Engine.new
+ r.attribute :percentage, Attributes::Float
+ end
+ end
+
+ def type_cast(val)
+ @relation[:percentage].type_cast(val)
+ end
+
+ describe "#type_cast" do
+ it "returns same value if an float" do
+ type_cast(24.01).should eql(24.01)
+ end
+
+ it "returns nil if passed nil" do
+ type_cast(nil).should be_nil
+ end
+
+ it "returns nil if passed empty string" do
+ type_cast('').should be_nil
+ end
+
+ it "returns float representation of a zero string float" do
+ type_cast('0').should eql(0.0)
+ end
+
+ it "returns float representation of a positive string integer" do
+ type_cast('24').should eql(24.0)
+ end
+
+ it "returns float representation of a positive string integer with spaces" do
+ type_cast(' 24').should eql(24.0)
+ type_cast('24 ').should eql(24.0)
+ end
+
+ it "returns float representation of a negative string float" do
+ type_cast('-24.23').should eql(-24.23)
+ end
+
+ it "returns float representation of a negative string integer with spaces" do
+ type_cast('-24 ').should eql(-24.0)
+ type_cast(' -24').should eql(-24.0)
+ end
+
+ it "returns integer representation of a zero string float" do
+ type_cast('0.0').should eql(0.0)
+ end
+
+ it "returns integer representation of a positive string float" do
+ type_cast('24.35').should eql(24.35)
+ end
+
+ it "returns integer representation of a positive string float with spaces" do
+ type_cast(' 24.35').should eql(24.35)
+ type_cast('24.35 ').should eql(24.35)
+ end
+
+ it "returns integer representation of a negative string float" do
+ type_cast('-24.35').should eql(-24.35)
+ end
+
+ it "returns integer representation of a negative string float with spaces" do
+ type_cast(' -24.35 ').should eql(-24.35)
+ end
+
+ it "returns integer representation of a zero string float, with no leading digits" do
+ type_cast('.0').should eql(0.0)
+ end
+
+ it "returns integer representation of a zero string float, with no leading digits with spaces" do
+ type_cast(' .0').should eql(0.0)
+ end
+
+ it "returns integer representation of a positive string float, with no leading digits" do
+ type_cast('.41').should eql(0.41)
+ end
+
+ it "returns integer representation of a zero float" do
+ type_cast(0.0).should eql(0.0)
+ end
+
+ it "returns integer representation of a positive float" do
+ type_cast(24.35).should eql(24.35)
+ end
+
+ it "returns integer representation of a negative float" do
+ type_cast(-24.35).should eql(-24.35)
+ end
+
+ it "returns integer representation of a zero decimal" do
+ type_cast(BigDecimal('0.0')).should eql(0.0)
+ end
+
+ it "returns integer representation of a positive decimal" do
+ type_cast(BigDecimal('24.35')).should eql(24.35)
+ end
+
+ it "returns integer representation of a negative decimal" do
+ type_cast(BigDecimal('-24.35')).should eql(-24.35)
+ end
+
+ [ Object.new, true, '00.0', '0.', 'string' ].each do |value|
+ it "raises exception when attempting type_cast of non-numeric value #{value.inspect}" do
+ lambda do
+ type_cast(value)
+ end.should raise_error(TypecastError, /could not typecast/)
+ end
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 61916e4

Please sign in to comment.