kitaro-tn
3/30/2018 - 9:33 AM

ActiveRecord attributeとas_json(serializable_hash)

attributesとas_json(serializable_hash)の違い

DBに依存しないattributeの追加

class StorageMetadatum < ApplicationRecord
 
  validates :file_name, presence: true, length: { maximum: 64 }
  validates :size, presence: true, numericality: true

  attribute :human_size, :string

  ##
  # convert human size
  # @return [String]
  def human_size
    ActiveSupport::NumberHelper.number_to_human_size(self.size)
  end

end

4.2以降ではattr_accessorではなく、attributeが使用可能

attribute(name, cast_type = Type::Value.new, **options)

hash化

  • attributes
storage_metadata = StorageMetadatum.find(1)
puts storage_metadata.attributes
=> {"id"=>1,
 "created_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "updated_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "file_name"=>"README.md",
 "file_type"=>nil,
 "size"=>460,
 "human_size"=>nil}
  • serializable_hash
storage_metadata.serializable_hash
=> {"id"=>1,
 "created_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "updated_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "file_name"=>"README.md",
 "file_type"=>nil,
 "size"=>460,
 "human_size"=>"460 Bytes"}
  • as_json
storage_metadata.as_json
=> {"id"=>1,
 "created_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "updated_at"=>Fri, 30 Mar 2018 09:01:59 UTC +00:00,
 "file_name"=>"README.md",
 "file_type"=>nil,
 "size"=>460,
 "human_size"=>"460 Bytes"}

Why?

  • attributesはAttributeSetクラスのインスタンス生成時に設定される

https://github.com/rails/rails/blob/1a4eb55a827a8641c19e03219d881f4aaba9748b/activemodel/lib/active_model/attribute_set.rb#L11

findやnew等のコール時にAttributeSetのコンストラクタが呼ばれる

  • serializable_hashはActiveModel::Serializationモジュールのメソッド

https://github.com/rails/rails/blob/1a4eb55a827a8641c19e03219d881f4aaba9748b/activemodel/lib/active_model/serialization.rb#L126

  • as_jsonはActiveModel::Serializerz::Jsonモジュールのメソッド

https://github.com/rails/rails/blob/1a4eb55a827a8641c19e03219d881f4aaba9748b/activemodel/lib/active_model/serializers/json.rb

ともにserializable_hashメソッド内部で該当するattributeをreadして利用している そのため、human_sizeメソッドを内部で読んでいる