Active Record attribute methodまとめ（その③: PrimaryKey編）

# はじめに
今回はActiveRecordのattribute methodのうち、PrimaryKeyメソッドをまとめていきます。
（2022年9月時点。Rails7.0対応。）
[BeforeTypeCastメソッド](https://qiita.com/maabow/items/33ad5328b192e3adb49e)、[Dirtyメソッド](https://qiita.com/maabow/items/0a5a228fb6c1447877e0)は全attributeに関連するメソッドでしたが、今回は主キー専用のメソッドになります。
関連したメソッドも多いので、[BeforeTypeCastメソッド](https://qiita.com/maabow/items/33ad5328b192e3adb49e)、[Dirtyメソッド](https://qiita.com/maabow/items/0a5a228fb6c1447877e0)の内容も確認してみてください。
PrimaryKeyメソッドを使う機会は多くはないかもしれませんが「こんなのもあるんだ〜」程度に知っておいて損はないと思います。

# 検証環境
以下のschemaとmodelに基づいて検証を行なっています。
``` Ruby
# db/schema.rb
create_table "todos", charset: "utf8mb4", force: :cascade do |t|
  t.string "identification_key"
  t.string "title"
  t.datetime "schedule_at"
  t.integer "status"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

# app/model/todo.rb
class Todo < ApplicationRecord
  before_save :set_primary_key

  self.primary_key = 'identification_key'
  enum status: { not_yet: 0, complete: 1, in_progress: 2, cancel: 3 }

  private

  def set_primary_key
    self.identification_key ||= SecureRandom.alphanumeric(16) if self.new_record?
  end
end
```

# PrimaryKey


## id
主キーの値を返却します。
独自に主キーを指定している場合は、その値が返却されます。
``` Ruby
@todos = Todo.all #=> [#<Todo id: 1, identification_key: "Idna0yEqHI32v25X",...>, #<Todo id: 2, ...>, ...]
@todos[0].id #=> "Idna0yEqHI32v25X"
```

## id=
主キーに値をセットすることができます。
``` Ruby
@todos = Todo.all #=> [#<Todo id: 1, identification_key: "Idna0yEqHI32v25X",...>, #<Todo id: 2, ...>, ...]
@todos[0].id = "abcdefghijklmn"
@todos[0].save!
@todos = Todo.all #=> [#<Todo id: 1, identification_key: "abcdefghijklmn",...>, #<Todo id: 2, ...>, ...]
@todos[0].id #=> "abcdefghijklmn"
```

## id?
主キーの値が存在するかどうかを返却します。
``` Ruby
todo = Todo.new #=> #<Todo id: nil, identification_key: nil,...>
todo.id? #=> false
todo.id = "abc"
todo.id? #=> true
```

## id_before_type_cast
主キーの型キャスト前の値が取得可能です。
``` Ruby
todo = Todo.new(identification_key: 123)
# 主キーはStringなので文字列で返却される
todo.id #=> "123"
# Integerで値をセットしているので、型キャスト前の値を取得するとIntegerで返却される
todo.id_before_type_cast #=> 123
```

## id_in_database, id_was
データベースに入っている主キーの値を返却します。
オブジェクトの状態から判断して返却しているので、メソッドが呼ばれるたびにSQLが流れるわけではありません。
下記のサンプルは`id_in_database`を使用していますが、`id_was`でも全く同じ動作をします。
この２つのメソッドは内部的にも全く同じ処理をしているので、いずれどちらかなくなるかもしれませんね。
``` Ruby
todo = Todo.new(identification_key: 123)
todo.id_in_database #=> nil

@todos = Todo.all #=> [#<Todo id: 1, identification_key: "abcdefghijklmn",...>, #<Todo id: 2, ...>, ...]
@todos[0].id_in_database #=> "abcdefghijklmn"
@todos[0].id = "abcdefg"
@todos[0].id_in_database #=> "abcdefghijklmn"
@todos[0].save!
@todos[0].id_in_database #=> "abcdefg"
```

## to_key
主キーの値が存在する時、主キーを配列で返却します。
主キーの値が存在しない時はnilを返却します。
``` Ruby
todo = Todo.new
todo.to_key #=> nil
todo.id = 123
todo.to_key #=> ["123"]
```

# おわりに
今回は、PrimaryKeyメソッドについてまとめていきました。
[BeforeTypeCastメソッド](https://qiita.com/maabow/items/33ad5328b192e3adb49e)、[Dirtyメソッド](https://qiita.com/maabow/items/0a5a228fb6c1447877e0)から派生したメソッドが多かったですね。
使い所は少ないかもしれませんが、主キーに対して何か処理をしていることが明示的になるというメリットはあるかなと思います。機会があれば是非使ってみてください。

その他のメソッドについては、別記事でまとめています。↓↓
[ActiveRecord attribute methodまとめ（その①: BeforeTypeCast編）](https://qiita.com/maabow/items/33ad5328b192e3adb49e)
[ActiveRecord attribute methodまとめ（その②: Dirty編）](https://qiita.com/maabow/items/0a5a228fb6c1447877e0)
[Active Record attribute methodまとめ（その④: Query, Read, Write編）](https://qiita.com/maabow/items/3d704bde6c4531bbb0ac)

# 参考
- [rails github](https://github.com/rails/rails/tree/main/activerecord/lib/active_record/attribute_methods)
- [Railsガイド](https://railsguides.jp/)
- [ActiveRecord::AttributeMethods::PrimaryKey](https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey.html)