form_withのパラメーターの行き先の仕組み

form_withのパラメーターの行き先の仕組み

[form_with]を使うと、パラメーターの行き先をcreateアクション(POST)やupdateアクション(PATCH)などと良い感じで分けてくれるが、この仕組みを説明します。

[app/views ファイル]

<%= form_with model: @user, url: admin_user_path(@user), local: true do |f| %>

Railsは、form_withに渡しているmodelのインスタンスの状態を見てcreateアクション(POST)やupdateアクション(PATCH)などの行き先を判断している

persisted?というメソッドを使い、@new_recordと@destroyedの2つのインスタンス変数にアクセスして状態を確認している
@new_recordと@destroyedのインスタンス変数とは、作成したオブジェクトが持っているインスタンス変数
persisted?がtrueならPATCHへパラメーターが送られる
persisted?がfalseならPOSTへパラメーターが送られる

persisted?メソッドの挙動とオブジェクトが持つインスタンス変数は、以下のイメージ

# DBに保存済みのインスタンスと未保存のインスタンスを用意します。
>> persisted_user = User.first
>> new_user = User.new

# @new_recordと@destroyedというインスタンス変数を持っているのか確認します。
>> persisted_user.instance_variables
# => [:@attributes, :@aggregation_cache, :@association_cache, :@readonly, :@destroyed, :@marked_for_destruction, :@destroyed_by_association, :@new_record, :@_start_transaction_state, :@transaction_state]
>> new_user.instance_variables
# => [:@attributes, :@aggregation_cache, :@association_cache, :@readonly, :@destroyed, :@marked_for_destruction, :@destroyed_by_association, :@new_record, :@_start_transaction_state, :@transaction_state]

# それぞれのインスタンス変数の値を確認します
>> persisted_user.instance_variable_get('@new_record')
# => false
>> persisted_user.instance_variable_get('@destroyed')
# => false
>> persisted_user.persisted?
# => true

>> new_user.instance_variable_get('@new_record')
# => true
>> new_user.instance_variable_get('@destroyed')
# => false
>> new_user.persisted?
# => false

# ちなみに削除済みも確認してみる
>> destroyed_user = persisted_user.destroy
>> destroyed_user.instance_variable_get('@new_record')
# => false
>> destroyed_user.instance_variable_get('@destroyed')
# => true
> destroyed_user.persisted?
# => false

参考記事:

Rubyでオブジェクトの中身を調べてみようを現役エンジニアが解説【初心者向け】 | TechAcademyマガジン