diff options
Diffstat (limited to 'activerecord/lib/active_record/attribute.rb')
-rw-r--r-- | activerecord/lib/active_record/attribute.rb | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb new file mode 100644 index 0000000000..f78cde23c5 --- /dev/null +++ b/activerecord/lib/active_record/attribute.rb @@ -0,0 +1,56 @@ +module ActiveRecord + class Attribute # :nodoc: + class << self + def from_database(value, type) + FromDatabase.new(value, type) + end + + def from_user(value, type) + FromUser.new(value, type) + end + end + + attr_reader :value_before_type_cast, :type + + # This method should not be called directly. + # Use #from_database or #from_user + def initialize(value_before_type_cast, type) + @value_before_type_cast = value_before_type_cast + @type = type + end + + def value + # `defined?` is cheaper than `||=` when we get back falsy values + @value = type_cast(value_before_type_cast) unless defined?(@value) + @value + end + + def value_for_database + type.type_cast_for_database(value) + end + + def type_cast + raise NotImplementedError + end + + protected + + def initialize_dup(other) + if defined?(@value) && @value.duplicable? + @value = @value.dup + end + end + + class FromDatabase < Attribute + def type_cast(value) + type.type_cast_from_database(value) + end + end + + class FromUser < Attribute + def type_cast(value) + type.type_cast_from_user(value) + end + end + end +end |