1:1の関係のモデル同士を関連づけ、フォームにそれぞれのモデルデータを同時に送信できるようにしたい。
つまり、formメソッド内で、2つのデータモデルを扱えるようにするのが今回の目的になります。
今回は、UserモデルとUser_profileモデルを1:1の関係性にして、formメソッド内でどちらのユーザー情報も同時に編集できるようにします。
#M
class CreateUserProfiles < ActiveRecord::Migration[6.0]
def change
create_table :user_profile do |t|
t.string :twitter_url
t.string :program_lang
t.string :image
t.references :user, foreign_key: true
t.timestamps
end
end
end
t.references :user, foreign_key: true
外部キーを設定することで、UserモデルとUser_profileモデルを紐付けます。
$ rails db:migrate
class Prof < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_one :user_profile
accepts_nested_attributes_for :user_profile
end
accepts_nested_attributes_for :user_profile
は、ネストされるフォームデータに備えてのものになります。
具体的には、ストロングパラメータ時に{ user: { user_profile_attributes: { program_lang: 〇〇, twitter_url: 〇〇, image: 〇〇 } } }
という形でまとめることができます。
#C
def create
@user = User.new(user_params)
@user.build_user_profile
if @user.save
・・・
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, user_profile_attributes: [:id, :program_lang, :twitter_url, :image])
end
ここで、注目すべきなのが@user.build_user_profile
。
あらかじめuser_profileモデルのインスタンスの作成をしていないと、View側のフォームが表示されません。
#V
.container
= form_with model: @user, local: true do |form|
= form.fields_for :user_profile do |prof|
.form-image
= prof.file_field :image
.form-group
= form.text_field :name
= form.text_field :email
= form.fields_for :user_profile do |prof|
.form-group
= prof.text_field :program_lang
= prof.text_field :twitter_url
.row
= form.submit "編集"
フォームの中にさらに別のモデルデータを認識してくれるのが、fields_for
。
フォームの中にフォームを作ることで、編集ボタン
を押すだけでまとめてサーバー側にデータを送信してくれます。