ブログのような何か

Rails関連の備忘録だったり、個人的なメモだったり・・

Railsのアソシエーションと複数登録 ~修正画面~

前回の続き

残りの修正画面を作成する

Editの作成

 before_action :set_profile, only: [:edit, :confirm, :update]

 def edit
 end

 def set_profile
    @profile = Profile.find(current_user.profile.id) if current_user.profile.present?
 end

editを追加する。
@profileのセットは edit,confirm,updateの3箇所で必要なので、まとめてbefore_actionに設定。
ただしconfirmはnewから経由した場合は不要なので、current_userのprofileがある場合のみ。

Confirmの修正

NewとEditの両方から遷移するので、if分で分岐させる。

  def confirm
    if @profile
      @profile.assign_attributes(profile_params)
      render :edit if @profile.invalid?
    else
      @profile = current_user.build_profile(profile_params)
      render :new if @profile.invalid?
    end
  end

newの場合はまだレコードができていないので、current_user.build_で良いが、Editの場合既にレコードが存在するので使えない。
この場合は.assign_attributesを使いparamsを仮セット出来る。

ただし、このままだと一点があり、deleteしたはずのデータがconfirm画面に表示されてしまう。
(勝手に消されても困るが・・)

# game_careersに4レコード登録した状態でEdit画面でレコードid14と15を
# deleteボタンで削除し、確認画面へ遷移する

GameCareer Load (0.5ms)  SELECT "game_careers".* FROM "game_careers" WHERE "game_careers"."profile_id" = $1  [["profile_id", 12]]
=> [#<GameCareer:0x00007f8df1ca5a68 id: 12, profile_id: 12, name: "test1">,
 #<GameCareer:0x00007f8df1ca5298 id: 13, profile_id: 12, name: "test2">,
 #<GameCareer:0x00007f8df1ca4870 id: 14, profile_id: 12, name: "test3">,
 #<GameCareer:0x00007f8df1ca4050 id: 15, profile_id: 12, name: "test4">]

# Confirm画面のprams
profile_params[:game_careers_attributes]
=> <ActionController::Parameters{
"0"=><ActionController::Parameters {"id"=>"12", "name"=>"test1"} permitted: true>, 
"1"=><ActionController::Parameters {"id"=>"13", "name"=>"test2"} permitted: true>, 
"2"=><ActionController::Parameters {"id"=>"14", "name"=>"test3", "_destroy"=>"1"} permitted: true>,
"3"=><ActionController::Parameters {"id"=>"15", "name"=>"test4", "_destroy"=>"1"} permitted: true>
} permitted: true>

そこでView側を修正。_destroyがtrueの場合は確認画面で表示しないようにする。

<% @profile.game_careers.each do |c| %>
 # _destoryがtrueの場合は表示しない
 <%= c.name  unless c._destroy %>
<% end %>

確認画面には戻るボタンが必要なので、それも追加する。
link_to :back(ブラウザのBack)だと、validationが絡んだ場合にエラーを起こすので、ちゃんとsubmitする。

方法は色々あるが、今回はsubmitボタンの名前を使って分岐する仕組みにする。

クリックしたsubmitの名前が[戻る]かどうかチェックするメソッドを作成。

def submit_back?
  params[:commit] == I18n.t('helpers.submit.back') 
end

それをcreateとupdateに組み込む。

  def create
    @profile = current_user.build_profile(profile_params)
    if !submit_back? && @profile.valid?
      @profile.save!
      redirect_to root_path
    else
      render :new
    end
  end

  def update
    @profile.assign_attributes(profile_params)
    if !submit_back? && @profile.valid?
      @profile.save!
      redirect_to root_path
    else
      render :edit
    end
  end

こうすることで、ちゃんと値を渡しつつ確認画面から戻る事ができる。
基本的な登録画面が完成したので、次は必要なバリデーションを実装する。