module ActiveRecord module Type class Value attr_reader :precision, :scale, :limit def initialize(precision: nil, limit: nil, scale: nil) @precision = precision @scale = scale @limit = limit end def type; end # :nodoc: # Convert a value from database input to the appropriate ruby type. The # return value of this method will be returned from # +ActiveRecord::AttributeMethods::Read#read_attribute+. See also # +type_cast+ and +cast_value+ # # +value+ The raw input, as provided from the database def type_cast_from_database(value) type_cast(value) end # Type casts a value from user input (e.g. from a setter). This value may # be a string from the form builder, or a ruby object passed to a setter. # There is currently no way to differentiate between which source it came # from. # # The return value of this method will be returned from # +ActiveRecord::AttributeMethods::Read#read_attribute+. See also: # +type_cast+ and +cast_value+ # # +value+ The raw input, as provided to the attribute setter. def type_cast_from_user(value) type_cast(value) end # Cast a value from the ruby type to a type that the database knows how # to understand. The returned value from this method should be a # +String+, +Numeric+, +Date+, +Time+, +Symbol+, +true+, +false+, or # +nil+ def type_cast_for_database(value) value end # Type cast a value for schema dumping. This method is private, as we are # hoping to remove it entirely. def type_cast_for_schema(value) # :nodoc: value.inspect end # These predicates are not documented, as I need to look further into # their use, and see if they can be removed entirely. def text? # :nodoc: false end def number? # :nodoc: false end def binary? # :nodoc: false end def klass # :nodoc: end # Determines whether a value has changed for dirty checking. +old_value+ # and +new_value+ will always be type-cast. Types should not need to # override this method. def changed?(old_value, new_value, _new_value_before_type_cast) old_value != new_value end # Determines whether the mutable value has been modified since it was # read. Returns +false+ by default. If your type returns an object # which could be mutated, you should override this method. You will need # to either: # # - pass +new_value+ to +type_cast_for_database+ and compare it to # +raw_old_value+ # # or # # - pass +raw_old_value+ to +type_cast_from_database+ and compare it to # +new_value+ # # +raw_old_value+ The original value, before being passed to # +type_cast_from_database+. # # +new_value+ The current value, after type casting. def changed_in_place?(raw_old_value, new_value) false end def ==(other) self.class == other.class && precision == other.precision && scale == other.scale && limit == other.limit end private # Convenience method. If you don't need separate behavior for # +type_cast_from_database+ and +type_cast_from_user+, you can override # this method instead. The default behavior of both methods is to call # this one. See also +cast_value+ def type_cast(value) # :doc: cast_value(value) unless value.nil? end # Convenience method for types which do not need separate type casting # behavior for user and database inputs. Called by # +type_cast_from_database+ and +type_cast_from_user+ for all values # except +nil+. def cast_value(value) # :doc: value end end end end