Oba-eng / curry_web

0 stars 0 forks source link

戻るボタンクリック時にパラメータが受け取れない #32

Open Oba-eng opened 5 months ago

Oba-eng commented 5 months ago

メニュー作成画面→確認画面へをクリック→確認画面に遷移(ここまで問題なく動いてます)→戻るをクリック

schema.rb
ActiveRecord::Schema.define(version: 2024_05_20_014130) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "contacts", force: :cascade do |t|
    t.string "name", null: false
    t.string "email", null: false
    t.string "subject", null: false
    t.text "message", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "favorites", force: :cascade do |t|
    t.bigint "user_id"
    t.bigint "menu_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["menu_id"], name: "index_favorites_on_menu_id"
    t.index ["user_id"], name: "index_favorites_on_user_id"
  end

  create_table "menus", force: :cascade do |t|
    t.string "name", null: false
    t.text "material", default: [], array: true
    t.text "quantity", default: [], array: true
    t.text "make", default: [], array: true
    t.text "point", null: false
    t.text "menu_image"
    t.bigint "user_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "genre", default: "未分類", null: false
    t.string "hot", default: "未分類", null: false
    t.index ["user_id"], name: "index_menus_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name", null: false
    t.string "email", null: false
    t.string "crypted_password"
    t.string "salt"
    t.string "menu_image"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  add_foreign_key "favorites", "menus"
  add_foreign_key "favorites", "users"
  add_foreign_key "menus", "users"
end
menus_controller.rb
class MenusController < ApplicationController
  before_action :set_menu, only: %i[ show edit update destroy ]
  skip_before_action :require_login, only: %i[index]

  def index
    @menus = Menu.all
    @q = Menu.ransack(params[:q])
    @menus = @q.result(distinct: true).includes(:user).page(params[:page]).order("created_at desc")
  end

  def show
    @q = Menu.ransack(params[:q])
  end

  def new
    @menu = Menu.new
    @q = Menu.ransack(params[:q])

    if session[:menu_params]
      @menu.attributes = session[:menu_params]
      @menu.material = session[:menu_params][:material] || ['']
      @menu.quantity = session[:menu_params][:quantity] || ['']
      @menu.make = session[:menu_params][:make] || ['']
      session.delete(:menu_params)
    else
      @menu.material = [''] if @menu.material.blank?
      @menu.quantity = [''] if @menu.quantity.blank? 
      @menu.make = [''] if @menu.make.blank? 
    end
  end

  def edit
    @menu = Menu.find(params[:id])
    @q = Menu.ransack(params[:q])
  end

  def create
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if params[:back]
      session[:menu_params] = menu_params
      redirect_to new_menu_path and return
    end

    unless @menu.save
      render :new and return
    end

    redirect_to @menu, notice: 'Menu was successfully created.'
  end

  def update
    @q = Menu.ransack(params[:q])
    respond_to do |format|
      if @menu.update(menu_params)
        format.html { redirect_to menu_url(@menu), success: '更新しました' }
        format.json { render :show, status: :ok, location: @menu }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @menu.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    menu = Menu.find(params[:id])
    menu.destroy
    redirect_to menus_url, success: '削除しました'
  end

  def favorites
    @favorites_menus = current_user.favorite_menus.includes(:user).order(created_at: :desc)
  end

  def confirm_new
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if @menu.valid?
      render :confirm_new
    else
      render :new
    end
  end

  private
    def set_menu
      @menu = Menu.find(params[:id])
    end

    def menu_params
      params.require(:menu).permit(:name, :genre, :hot, :point, :menu_image, :menu_image_cache, material: [], quantity: [], make: [])
    end
end
confirm_new.html.erb
<%= form_with model: @menu, local: true do |f| %>
  <div class="card-body">
    <h1>
      <%= @menu.name %>
    </h1>
    <div>
      <%= image_tag @menu.menu_image.url, class: 'w-100 mb-3' %>
    </div>

    <!-- 材料と分量のリストを表示 -->
    <div class="card mb-3">
      <div class="card-header">
        材料と分量
      </div>
      <ul class="list-group list-group-flush">
        <% @menu.material.each_with_index do |material, index| %>
          <li class="list-group-item d-flex justify-content-between">
            <span><%= material %></span>
            <span><%= @menu.quantity[index] %></span>
          </li>
        <% end %>
      </ul>
    </div>

    <div class="card mb-3">
      <div class="card-header">
        作り方
      </div>
      <div class="card-body">
        <% @menu.make.each_with_index do |step, index| %>
          <div class="card mb-3">
            <div class="card-header">
              ステップ<%= index + 1 %>
            </div>
            <div class="card-body">
              <p><%= Rinku.auto_link(simple_format(step), :all, 'target="_blank"').html_safe %></p>
            </div>
          </div>
        <% end %>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header">
        ポイント
      </div>
      <div class="card-body">
        <%= @menu.point %>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header">
        カレーのジャンル
      </div>
      <div class="card-body">
        <%= @menu.genre %>
      </div>
    </div>

    <div class="card mb-3">
      <div class="card-header">
        辛さレベル
      </div>
      <div class="card-body">
        <%= @menu.hot %>
      </div>
    </div>

    <% if current_user&.own?(@menu) %>
      <%= f.hidden_field :name %>

      <% @menu.material.each_with_index do |material, index| %>
        <%= f.hidden_field "material[]", value: material %>
      <% end %>

      <% @menu.quantity.each_with_index do |quantity, index| %>
        <%= f.hidden_field "quantity[]", value: quantity %>
      <% end %>

      <% @menu.make.each_with_index do |make, index| %>
        <%= f.hidden_field "make[]", value: make %>
      <% end %>

      <%= f.hidden_field :point %>
      <%= f.hidden_field :menu_image_cache %>
      <%= f.hidden_field :genre %>
      <%= f.hidden_field :hot %>
      <%= f.submit '戻る', name: 'back', class: 'btn btn-primary ml-2' %>
    <% end %>
    <%= f.submit '公開する', class: 'btn btn-primary ml-2' %>
  </div>
<% end %>
routes.rb
Rails.application.routes.draw do
  root 'menus#index'

  resources :users do
    member do
      get :favorites
    end
  end

  resources :menus do
    member do
      post :favorite, to: 'favorites#create'
    end

    resource :favorite, only: [:destroy]

    collection do
      post :confirm_new, action: :confirm_new
    end
  end

  namespace :mypage do
    resources :tree, only: [:index]
  end

  resources :sessions, only: [:new, :create, :destroy]

  delete 'logout', to: 'sessions#destroy'
  get 'logout', to: 'sessions#destroy', as: :logout_get

  # フッターのリンクを作成
  get 'privacy', to: 'pages#privacy', as: :privacy
  get 'terms', to: 'pages#terms', as: :terms

  # お問い合わせメール
  namespace :public do
    resources :contacts, only: [:new, :create] do
      collection do
        post 'confirm'
        post 'back'
        get 'done'
      end
    end
  end
end

material、quantity、makeのカラムは配列として扱っているためここが原因であると考えています。

createアクションとconfirm_newアクションで@menuに値が入っているかを確認。 →結果としてcreateアクションでは@menuに値が入ってない。 confirm_newアクションでは@menuに値が入っていることが確認できた。

confirm_newアクションでは動くのにcreateアクションでは動かない理由を検索してみましたが原因がわかりませんでした。

From: /Users/oobarikuto/workspace/curry_web/-curry_web/carry_web/app/controllers/menus_controller.rb:41 MenusController#create:

    37: def create
    38:   @q = Menu.ransack(params[:q])
    39:   @menu = current_user.menus.new(menu_params)
    40:   binding.pry
 => 41:   if params[:back]
    42:     session[:menu_params] = menu_params
    43:     redirect_to new_menu_path and return
    44:   end
    45:   
    46:   unless @menu.save
    47:     render :new and return
    48:   end
    49: 
    50:   redirect_to @menu, notice: 'Menu was successfully created.'
    51: end

[1] pry(#<MenusController>)> @menu
=> #<Menu:0x000000013df70d58
 id: nil,
 name: "qaaaa",
 material: [],
 quantity: [],
 make: [],
 point: "sss",
 menu_image: nil,
 user_id: 1,
 created_at: nil,
 updated_at: nil,
 genre: "グリーンカレー",
 hot: "2:甘口〜中辛">
[2] pry(#<MenusController>)> 

createアクションが走った時にはmaterial: [],quantity: [],make: [],が空でパラメータが受け取れていなかったです。

https://qiita.com/anago1030/items/0016bbf99e7fe3b926e1

https://qiita.com/i_garasi/items/81952e8198308d70069e

Rails 6.1.4

ruby 3.0.2

kenchasonakai commented 5 months ago

参考にしている下記の記事と実装内容を変えている箇所はありますか? https://qiita.com/ngron/items/d55aac6e81a9fb2fe81c

Oba-eng commented 5 months ago

createアクションは変えてあります。 参考記事のコードだと配列を受け取れなかったためチャットGPTに聞きながらコードを変更しました。 sessionを使うといいと返答があったためそちらを使用してみましたがこれもうまくいってません。

  def create
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if params[:back]
      session[:menu_params] = menu_params
      redirect_to new_menu_path and return
    end

    unless @menu.save
      render :new and return
    end

    redirect_to @menu, notice: 'Menu was successfully created.'
  end
kenchasonakai commented 5 months ago

以前の実装方法の確認

参考記事と同じ形の実装方法をしていた時は何が原因で配列が受け取れなかったのでしょうか? エラーなどの記録は残っていますか?

現在の実装方法の確認

sessionを使う場合はsessionを参照しないといけないと思いますが、下記の記述や下記の記述にかかわるどこかでsession情報を取得する処理は行っていますでしょうか?

    <% if current_user&.own?(@menu) %>
      <%= f.hidden_field :name %>

      <% @menu.material.each_with_index do |material, index| %>
        <%= f.hidden_field "material[]", value: material %>
      <% end %>

      <% @menu.quantity.each_with_index do |quantity, index| %>
        <%= f.hidden_field "quantity[]", value: quantity %>
      <% end %>

      <% @menu.make.each_with_index do |make, index| %>
        <%= f.hidden_field "make[]", value: make %>
      <% end %>
Oba-eng commented 5 months ago

すいません、コロコロコード変えながらやっていたため記録は残ってませんでした。 ただ、エラーは発生していないため原因がわからないです。 createアクションでデバックをしてみましたが戻るボタンを押した時に配列が消えてしまってます。

sessionはコントローラーで参照しているため問題ないかなと思ってます。正直あんまりここは理解できていないです。

  def new
    @menu = Menu.new
    @q = Menu.ransack(params[:q])

    if session[:menu_params]
      @menu.attributes = session[:menu_params]
      @menu.material = session[:menu_params][:material] || ['']
      @menu.quantity = session[:menu_params][:quantity] || ['']
      @menu.make = session[:menu_params][:make] || ['']
      session.delete(:menu_params)
    else
      @menu.material = [''] if @menu.material.blank?
      @menu.quantity = [''] if @menu.quantity.blank? 
      @menu.make = [''] if @menu.make.blank? 
    end
  end
  def create
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if params[:back]
      session[:menu_params] = menu_params
      redirect_to new_menu_path and return
    end

    unless @menu.save
      render :new and return
    end

    redirect_to @menu, notice: 'Menu was successfully created.'
  end
kenchasonakai commented 5 months ago

createアクションのif params[:back]が動いてredirect_to new_menu_path and returnでnewアクションが動くときbinding.pryなどを使ってnewアクションの中でsession[:menu_params]の値が参照できるか確認してみてください

Oba-eng commented 5 months ago
Started POST "/menus/confirm_new" for ::1 at 2024-05-29 02:28:26 +0900
Processing by MenusController#confirm_new as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Rncc8KDKTXSCc+twaEoKD/ePU+lePfz5RbA1xC2dFQjh4uy9I6ndS1cxw5XpNtjMe0yxo8WZcyDAbeCaPL5s9g==", "menu"=>{"name"=>"aaaa", "material"=>["ss", "dd"], "quantity"=>["ss", "dd"], "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口", "make"=>["ddd", "fff"], "point"=>"ccc"}, "commit"=>"確認画面へ"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:9:in `current_user'
  Rendering layout layouts/application.html.erb
  Rendering menus/new.html.erb within layouts/application
  Rendered menus/_form.html.erb (Duration: 14.2ms | Allocations: 8588)
  Rendered menus/new.html.erb within layouts/application (Duration: 14.4ms | Allocations: 8658)
  Rendered shared/_search.html.erb (Duration: 0.4ms | Allocations: 731)
  Rendered shared/_header.html.erb (Duration: 0.7ms | Allocations: 1029)
  Rendered shared/_flash_message.html.erb (Duration: 0.0ms | Allocations: 26)
  Rendered shared/_footer.html.erb (Duration: 0.0ms | Allocations: 60)
  Rendered layout layouts/application.html.erb (Duration: 34.8ms | Allocations: 36086)
Completed 200 OK in 67ms (Views: 35.7ms | ActiveRecord: 8.2ms | Allocations: 55327)

Started POST "/menus/confirm_new" for ::1 at 2024-05-29 02:28:33 +0900
Processing by MenusController#confirm_new as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"GmLddxSriD2v0GBwQrVmA/63kxxYvV++ps35m/Fp5W299y06l8gYAnqSSJXDybTAcnRxVsMZ0GcjECzF4Eqckw==", "menu"=>{"name"=>"aaaa", "menu_image"=>#<ActionDispatch::Http::UploadedFile:0x000000012b6f8138 @tempfile=#<Tempfile:/var/folders/hf/q6k9gjg123v0y44v2q1bz1680000gn/T/RackMultipart20240529-38407-wp95y2.png>, @original_filename="1e161a0ae12dcdc03814dd3822dd26c6.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"menu[menu_image]\"; filename=\"1e161a0ae12dcdc03814dd3822dd26c6.png\"\r\nContent-Type: image/png\r\n">, "material"=>["ss", "dd"], "quantity"=>["ss", "dd"], "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口", "make"=>["ddd", "fff"], "point"=>"ccc"}, "commit"=>"確認画面へ"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:9:in `current_user'
  Rendering layout layouts/application.html.erb
  Rendering menus/confirm_new.html.erb within layouts/application
  Rendered menus/confirm_new.html.erb within layouts/application (Duration: 1.3ms | Allocations: 1098)
  Rendered shared/_search.html.erb (Duration: 0.3ms | Allocations: 700)
  Rendered shared/_header.html.erb (Duration: 0.5ms | Allocations: 952)
  Rendered shared/_flash_message.html.erb (Duration: 0.0ms | Allocations: 18)
  Rendered shared/_footer.html.erb (Duration: 0.0ms | Allocations: 53)
  Rendered layout layouts/application.html.erb (Duration: 11.7ms | Allocations: 28493)
Completed 200 OK in 103ms (Views: 12.1ms | ActiveRecord: 0.3ms | Allocations: 32683)

Started POST "/menus" for ::1 at 2024-05-29 02:28:35 +0900
Processing by MenusController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"qD2aXYJzpKmNd5WGdPcQsAtHoAWgVksk5nw6OFHMJ+0PqGoQARA0llg1vWP1i8Jzh4RCTzvyxP1joe9mQO9eEw==", "menu"=>{"name"=>"aaaa", "material"=>[], "quantity"=>[], "make"=>[], "point"=>"ccc", "menu_image_cache"=>"1716917313-751601129752347-0002-6775/1e161a0ae12dcdc03814dd3822dd26c6.png", "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口"}, "back"=>"戻る"}
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:9:in `current_user'

From: /Users/oobarikuto/workspace/curry_web/-curry_web/carry_web/app/controllers/menus_controller.rb:44 MenusController#create:

    37: def create
    38:   @q = Menu.ransack(params[:q])
    39:   @menu = current_user.menus.new(menu_params)
    40:   
    41:   if params[:back]
    42:     session[:menu_params] = menu_params
    43:     binding.pry
 => 44:     redirect_to new_menu_path and return
    45:   end
    46:   
    47:   unless @menu.save
    48:     render :new and return
    49:   end
    50: 
    51:   redirect_to @menu, notice: 'Menu was successfully created.'
    52: end

[1] pry(#<MenusController>)> session[:menu_params]
=> #<ActionController::Parameters {"name"=>"aaaa", "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口", "point"=>"ccc", "menu_image_cache"=>"1716917313-751601129752347-0002-6775/1e161a0ae12dcdc03814dd3822dd26c6.png", "material"=>[], "quantity"=>[], "make"=>[]} permitted: true>
[2] pry(#<MenusController>)> @menu
=> #<Menu:0x000000013b270970
 id: nil,
 name: "aaaa",
 material: [],
 quantity: [],
 make: [],
 point: "ccc",
 menu_image: nil,
 user_id: 1,
 created_at: nil,
 updated_at: nil,
 genre: "ドライカレー",
 hot: "4:中辛〜辛口">
[3] pry(#<MenusController>)> 

createアクションが動いた時にはsession[:menu_params]にも@menuにも配列の値が消えている状態です。 @menuを使ってパラメーターを引き継げないかと考えて試してみました。

def create
    @q = Menu.ransack(params[:q])

    if params[:back]
      @menu = current_user.menus.new(menu_params)
      binding.pry
      render :new
      return
    end

    @menu = current_user.menus.new(menu_params)

    if @menu.save
      redirect_to @menu, notice: 'Menu was successfully created.'
    else
      render :new
    end
  end

  def confirm_new
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if @menu.valid?
      render :confirm_new
    else
      render :new
    end
  end
Started POST "/menus" for ::1 at 2024-05-29 02:18:17 +0900
Processing by MenusController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"p1bdzHgPkxfr0C7B864N9HMWNgX/rKf0J+GUWOX7B/QAwy2B+2wDKD6SBiRy0t83/9XUT2QIKC2iPEEG9Nh+Cg==", "menu"=>{"name"=>"aaaa", "material"=>[], "quantity"=>[], "make"=>[], "point"=>"ccc", "menu_image_cache"=>"1716916696-491914529147216-0001-7142/1e161a0ae12dcdc03814dd3822dd26c6.png", "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口"}, "back"=>"戻る"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:9:in `current_user'

From: /Users/oobarikuto/workspace/curry_web/-curry_web/carry_web/app/controllers/menus_controller.rb:42 MenusController#create:

    36: def create
    37:   @q = Menu.ransack(params[:q])
    38:   
    39:   if params[:back]
    40:     @menu = current_user.menus.new(menu_params)
    41:     binding.pry
 => 42:     render :new
    43:     return
    44:   end
    45: 
    46:   @menu = current_user.menus.new(menu_params)
    47:   
    48:   if @menu.save
    49:     redirect_to @menu, notice: 'Menu was successfully created.'
    50:   else
    51:     render :new
    52:   end
    53: end

[1] pry(#<MenusController>)> @menu
=> #<Menu:0x0000000122a0a0a0
 id: nil,
 name: "aaaa",
 material: [],
 quantity: [],
 make: [],
 point: "ccc",
 menu_image: nil,
 user_id: 1,
 created_at: nil,
 updated_at: nil,
 genre: "ドライカレー",
 hot: "4:中辛〜辛口">
[2] pry(#<MenusController>)> menu_params
=> #<ActionController::Parameters {"name"=>"aaaa", "genre"=>"ドライカレー", "hot"=>"4:中辛〜辛口", "point"=>"ccc", "menu_image_cache"=>"1716916696-491914529147216-0001-7142/1e161a0ae12dcdc03814dd3822dd26c6.png", "material"=>[], "quantity"=>[], "make"=>[]} permitted: true>
[3] pry(#<MenusController>)> 

こちらも@menuには配列の値を引き継げませんでした。 createアクション→newアクションの順番で動いていて、newアクションが動く前の段階で配列の値が消えています。

念の為newアクションでもデバッカー入れてみましたがnilになってます。

From: /Users/oobarikuto/workspace/curry_web/-curry_web/carry_web/app/controllers/menus_controller.rb:19 MenusController#new:

    15: def new
    16:   @menu = Menu.new
    17:   @q = Menu.ransack(params[:q])
    18:   binding.pry
 => 19:   if session[:menu_params]
    20:     @menu.attributes = session[:menu_params]
    21:     @menu.material = session[:menu_params][:material] || ['']
    22:     @menu.quantity = session[:menu_params][:quantity] || ['']
    23:     @menu.make = session[:menu_params][:make] || ['']
    24:     session.delete(:menu_params)
    25:   else
    26:     @menu.material = [''] if @menu.material.blank?
    27:     @menu.quantity = [''] if @menu.quantity.blank? 
    28:     @menu.make = [''] if @menu.make.blank? 
    29:   end
    30: end

[1] pry(#<MenusController>)> session[:menu_params]
=> nil
[2] pry(#<MenusController>)> 
kenchasonakai commented 5 months ago

そしたらsessionじゃなくて参考にしていた記事のやり方で進めると良いのではないでしょうか

また、配列型は中身に何が入っているのかDBを検索する時にわかりにくいので中間テーブルなどを使って扱うようにするのが一般的なやり方かなと思います

kenchasonakai commented 5 months ago

それかこのやり方で行くのであればまずsessionやインスタンス変数の仕様を理解して現状なぜ出来ないのか探っていくのが良いかと思います

Oba-eng commented 5 months ago

ありがとうございます。 https://kossy-web-engineer.hatenablog.com/entry/2018/10/19/063937 この記事を参考にしてbackアクションを追加して解決しました。

def confirm_new
    @q = Menu.ransack(params[:q])
    @menu = current_user.menus.new(menu_params)

    if @menu.valid?
      session[:menu] = @menu.attributes
      render :confirm_new
    else
      render :new
    end
  end

  def back
    @q = Menu.ransack(params[:q])
    @menu = Menu.new(session[:menu]) if session[:menu]
    render :new
  end

ただ、画像だけ戻るボタンをクリックした時に消えてしまうためここは自分でやってみます。 もしわからなかったら改めてissue立てて質問させていただきます!