aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/types
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/types')
-rw-r--r--activerecord/lib/active_record/types/number.rb30
-rw-r--r--activerecord/lib/active_record/types/object.rb37
-rw-r--r--activerecord/lib/active_record/types/serialize.rb33
-rw-r--r--activerecord/lib/active_record/types/time_with_zone.rb20
-rw-r--r--activerecord/lib/active_record/types/unknown.rb37
5 files changed, 157 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/types/number.rb b/activerecord/lib/active_record/types/number.rb
new file mode 100644
index 0000000000..cfbe877575
--- /dev/null
+++ b/activerecord/lib/active_record/types/number.rb
@@ -0,0 +1,30 @@
+module ActiveRecord
+ module Type
+ class Number < Object
+
+ def boolean(value)
+ value = cast(value)
+ !(value.nil? || value.zero?)
+ end
+
+ def precast(value)
+ convert_number_column_value(value)
+ end
+
+ private
+
+ def convert_number_column_value(value)
+ if value == false
+ 0
+ elsif value == true
+ 1
+ elsif value.is_a?(String) && value.blank?
+ nil
+ else
+ value
+ end
+ end
+
+ end
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/types/object.rb b/activerecord/lib/active_record/types/object.rb
new file mode 100644
index 0000000000..ec3f861abd
--- /dev/null
+++ b/activerecord/lib/active_record/types/object.rb
@@ -0,0 +1,37 @@
+module ActiveRecord
+ module Type
+ module Casting
+
+ def cast(value)
+ typecaster.type_cast(value)
+ end
+
+ def precast(value)
+ value
+ end
+
+ def boolean(value)
+ cast(value).present?
+ end
+
+ # Attributes::Typecasting stores appendable? types (e.g. serialized Arrays) when typecasting reads.
+ def appendable?
+ false
+ end
+
+ end
+
+ class Object
+ include Casting
+
+ attr_reader :name, :options
+ attr_reader :typecaster
+
+ def initialize(typecaster = nil, options = {})
+ @typecaster, @options = typecaster, options
+ end
+
+ end
+
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/types/serialize.rb b/activerecord/lib/active_record/types/serialize.rb
new file mode 100644
index 0000000000..7b6af1981f
--- /dev/null
+++ b/activerecord/lib/active_record/types/serialize.rb
@@ -0,0 +1,33 @@
+module ActiveRecord
+ module Type
+ class Serialize < Object
+
+ def cast(value)
+ unserialize(value)
+ end
+
+ def appendable?
+ true
+ end
+
+ protected
+
+ def unserialize(value)
+ unserialized_object = object_from_yaml(value)
+
+ if unserialized_object.is_a?(@options[:serialize]) || unserialized_object.nil?
+ unserialized_object
+ else
+ raise SerializationTypeMismatch,
+ "#{name} was supposed to be a #{@options[:serialize]}, but was a #{unserialized_object.class.to_s}"
+ end
+ end
+
+ def object_from_yaml(string)
+ return string unless string.is_a?(String) && string =~ /^---/
+ YAML::load(string) rescue string
+ end
+
+ end
+ end
+end \ No newline at end of file
diff --git a/activerecord/lib/active_record/types/time_with_zone.rb b/activerecord/lib/active_record/types/time_with_zone.rb
new file mode 100644
index 0000000000..3a8b9292f9
--- /dev/null
+++ b/activerecord/lib/active_record/types/time_with_zone.rb
@@ -0,0 +1,20 @@
+module ActiveRecord
+ module Type
+ class TimeWithZone < Object
+
+ def cast(time)
+ time = super(time)
+ time.acts_like?(:time) ? time.in_time_zone : time
+ end
+
+ def precast(time)
+ unless time.acts_like?(:time)
+ time = time.is_a?(String) ? ::Time.zone.parse(time) : time.to_time rescue time
+ end
+ time = time.in_time_zone rescue nil if time
+ super(time)
+ end
+
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/types/unknown.rb b/activerecord/lib/active_record/types/unknown.rb
new file mode 100644
index 0000000000..f832c7b304
--- /dev/null
+++ b/activerecord/lib/active_record/types/unknown.rb
@@ -0,0 +1,37 @@
+module ActiveRecord
+ module Type
+ # Useful for handling attributes not mapped to types. Performs some boolean typecasting,
+ # but otherwise leaves the value untouched.
+ class Unknown
+
+ def cast(value)
+ value
+ end
+
+ def precast(value)
+ value
+ end
+
+ # Attempts typecasting to handle numeric, false and blank values.
+ def boolean(value)
+ empty = (numeric?(value) && value.to_i.zero?) || false?(value) || value.blank?
+ !empty
+ end
+
+ def appendable?
+ false
+ end
+
+ protected
+
+ def false?(value)
+ ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
+ end
+
+ def numeric?(value)
+ Numeric === value || value !~ /[^0-9]/
+ end
+
+ end
+ end
+end \ No newline at end of file