# frozen_string_literal: true module ActiveRecord module AttributeMethods # = Active Record Attribute Methods Before Type Cast # # ActiveRecord::AttributeMethods::BeforeTypeCast provides a way to # read the value of the attributes before typecasting and deserialization. # # class Task < ActiveRecord::Base # end # # task = Task.new(id: '1', completed_on: '2012-10-21') # task.id # => 1 # task.completed_on # => Sun, 21 Oct 2012 # # task.attributes_before_type_cast # # => {"id"=>"1", "completed_on"=>"2012-10-21", ... } # task.read_attribute_before_type_cast('id') # => "1" # task.read_attribute_before_type_cast('completed_on') # => "2012-10-21" # # In addition to #read_attribute_before_type_cast and #attributes_before_type_cast, # it declares a method for all attributes with the *_before_type_cast # suffix. # # task.id_before_type_cast # => "1" # task.completed_on_before_type_cast # => "2012-10-21" module BeforeTypeCast extend ActiveSupport::Concern included do attribute_method_suffix "_before_type_cast", "_for_database", parameters: false attribute_method_suffix "_came_from_user?", parameters: false end # Returns the value of the attribute identified by +attr_name+ before # typecasting and deserialization. # # class Task < ActiveRecord::Base # end # # task = Task.new(id: '1', completed_on: '2012-10-21') # task.read_attribute('id') # => 1 # task.read_attribute_before_type_cast('id') # => '1' # task.read_attribute('completed_on') # => Sun, 21 Oct 2012 # task.read_attribute_before_type_cast('completed_on') # => "2012-10-21" # task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21" def read_attribute_before_type_cast(attr_name) name = attr_name.to_s name = self.class.attribute_aliases[name] || name attribute_before_type_cast(name) end # Returns the value of the attribute identified by +attr_name+ after # serialization. # # class Book < ActiveRecord::Base # enum :status, { draft: 1, published: 2 } # end # # book = Book.new(status: "published") # book.read_attribute(:status) # => "published" # book.read_attribute_for_database(:status) # => 2 def read_attribute_for_database(attr_name) name = attr_name.to_s name = self.class.attribute_aliases[name] || name attribute_for_database(name) end # Returns a hash of attributes before typecasting and deserialization. # # class Task < ActiveRecord::Base # end # # task = Task.new(title: nil, is_done: true, completed_on: '2012-10-21') # task.attributes # # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>Sun, 21 Oct 2012, "created_at"=>nil, "updated_at"=>nil} # task.attributes_before_type_cast # # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil} def attributes_before_type_cast @attributes.values_before_type_cast end # Returns a hash of attributes for assignment to the database. def attributes_for_database @attributes.values_for_database end private # Dispatch target for *_before_type_cast attribute methods. def attribute_before_type_cast(attr_name) @attributes[attr_name].value_before_type_cast end def attribute_for_database(attr_name) @attributes[attr_name].value_for_database end def attribute_came_from_user?(attr_name) @attributes[attr_name].came_from_user? end end end end