Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release0.0.7/item edit delete #100

Merged
merged 12 commits into from
Jun 13, 2023
Merged

Conversation

MIDO-ruby7
Copy link
Owner

No description provided.

@MIDO-ruby7
Copy link
Owner Author

MIDO-ruby7 commented Jun 12, 2023

質問内容・実現したいこと

画像のupdateで起こるエラーを解決したい。

現状発生している問題・エラーメッセージ

NoMethodError in ItemsController#update
undefined method `image_will_change!' for #<Item id: 25, name: "白ワインソーダ", size: nil, created_at: "2023-06-11 23:46:25.599337000 +0000", updated_at: "2023-06-11 23:46:25.599337000 +0000", user_id: 3, category_id: nil>
Did you mean?
size_will_change!
name_will_change!
スクリーンショット 2023-06-12 9 08 26

どの処理までうまく動いているのか

・画像の新規投稿は成功する
・ファイルをパラメータで飛ばすことはできている?
スクリーンショット 2023-06-12 9 08 32

該当のソースコード

機能の概要:ポケモン図鑑のようにお酒の商品名一意に対し、「捕まえたポケモン」の感じでユーザーが飲んだお酒の写真を複数紐付けて表示できるようにする機能です。

app/views/items/edit.html.erb

<h1>Items#new</h1>
<%= form_with model: @item,  local: true do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div>
    <%= f.label :name, class: "block mb-2 text-sm font-medium text-gray-900 dark:text-white" %>
    <%= f.text_field :name, class: "block text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400" %>
  <div>
    <%= f.label :image, class: "block mb-2 text-sm font-medium text-gray-900 dark:text-white" %>
    <%= f.file_field :image, class: "block text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400", accept: 'image/*', onchange: 'previewImage()' %>
    <%= f.hidden_field :image_cache %>
  </div>
  <div>
    <%= image_tag @item.image.url, id: 'preview', size: '300x200' %>
  </div>
  <%= f.submit '投稿', class: 'text-white bg-gradient-to-r from-cyan-400 via-cyan-500 to-cyan-600 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2' %>
<% end %>

app/controllers/items_controller.rb

class ItemsController < ApplicationController
  before_action :set_item, only: %i[edit update destroy]
  def index
    @items = Item.all.includes(:photos).order(created_at: :desc)
  end

  #画像のアップロード機能
  def new
    @item = Item.new
  end

  def create
    @item = current_user.items.find_or_initialize_by(name: item_params[:name])

    if @item.new_record?
      @item.save
      @item.photos.create(image: item_params[:image])
      redirect_to items_path, notice: '新種を登録しました'
    else
      @item.photos.create(image: item_params[:image])
      redirect_to root_path, notice: '画像を登録しました'
    end
  end

  def show
    @item = Item.find(params[:id])
  end

  def edit; end

  def update
    @item.update(item_params)
    redirect_to items_path, notice: '図鑑を更新しました'
  end

  def destroy
    @item.destroy
    redirect_to items_path, notice: '図鑑を削除しました', status: :see_other
  end

  private

  def item_params
    params.require(:item).permit(:name, :image, :image_cache, :size)
  end

  def set_item
    @item = current_user.items.find(params[:id])
  end
end

app/models/item.rb

class Item < ApplicationRecord
  belongs_to :user
  has_many :photos, dependent: :destroy
  mount_uploader :image, BoozeImageUploader
end

app/models/photo.rb

class Photo < ApplicationRecord
  belongs_to :item
  mount_uploader :image, BoozeImageUploader
end

db/schema.rb

# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_06_06_044020) do
  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "item_tags", force: :cascade do |t|
    t.bigint "item_id", null: false
    t.bigint "tag_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["item_id"], name: "index_item_tags_on_item_id"
    t.index ["tag_id"], name: "index_item_tags_on_tag_id"
  end

  create_table "items", force: :cascade do |t|
    t.string "name", null: false
    t.integer "size"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "user_id"
    t.index ["name"], name: "index_items_on_name", unique: true
    t.index ["user_id"], name: "index_items_on_user_id"
  end

  create_table "photos", force: :cascade do |t|
    t.bigint "item_id"
    t.string "image"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["item_id"], name: "index_photos_on_item_id"
  end

  create_table "tags", force: :cascade do |t|
    t.string "name", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "email", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
  end

  add_foreign_key "item_tags", "items"
  add_foreign_key "item_tags", "tags"
  add_foreign_key "items", "users"
  add_foreign_key "photos", "items"
end

エラーから考えられる原因

image_will_change!が定義していないにも関わらず発生しており、CarrierWaveが起因している。
・下記を見るとimageカラムがitemテーブルに無いことで発生していそう(1つの商品に対して複数の写真を投稿できるようにしたいのでphotoテーブルを作ってその中にimageカラムを入れて分けています)
https://stackoverflow.com/questions/7491595/carrierwave-rails-3-1-undefined-method-image-will-change
・@item.update(item_params)の中身確認するとNameError:が出ているのでパラメータの問題?

試したこと

・CarrierWaveのissue確認も言ってることがよくわからない…
carrierwaveuploader/carrierwave#274
・ @item.update(item_params)の中身確認

 @item.update(item_params)
NameError: undefined local variable or method `item_params' for #<Item id: 25, name: "白ワインソーダ", size: nil, created_at: "2023-06-11 23:46:25.599337000 +0000", updated_at: "2023-06-11 23:46:25.599337000 +0000", user_id: 3, category_id: nil>

ご助言いただけますと幸いです

@kenchasonakai
Copy link

複数画像アップロードを実装する際に参考にした記事などありますか?

https://kolosek.com/carrierwave-upload-multiple-images/
stackoverflowに載ってたこの辺とかやりたいことに近そうなので参考にしてみると良いかもです
https://stackoverflow.com/questions/59389458/how-to-upload-multiple-files-with-carrierwave-and-create-multiple-records

@MIDO-ruby7
Copy link
Owner Author

複数画像アップロードを実装する際に参考にした記事などありますか?

https://kolosek.com/carrierwave-upload-multiple-images/ stackoverflowに載ってたこの辺とかやりたいことに近そうなので参考にしてみると良いかもです https://stackoverflow.com/questions/59389458/how-to-upload-multiple-files-with-carrierwave-and-create-multiple-records

中井さんありがとうございます!頂いた記事のコードやcarrierwaveの設定参考になります。ありがとうございます🙏

書き方が悪くてすみません。現状としてはitem#newには複数アップロードは実装しておらず、1画像ずつの投稿機能です。
アバター画像のように1ユーザーに1つの画像データでなく、1つの商品情報に複数の写真が紐づいている状態を実装しています。(説明下手ですみません…)
スクリーンショット 2023-06-12 12 51 44
item#show
氷結に2個の画像が紐づいてる
スクリーンショット 2023-06-12 12 51 52
スクリーンショット 2023-06-12 12 51 57

@kerochelo
Copy link

photosテーブルのimageカラム名あたりが怪しいかもです…

…nd %>の中身が表示されないエラーを解決し、new,editともに正常に動くようコードを修正
@kenchasonakai
Copy link

Itemはimage持たないように設計してると思うのですが、item_paramsそのまま渡しててimageカラムを更新しようとしてしまっているのが原因かと思います

下記の感じの処理が動いてしまっているがitemには#<Item:0x0000ffff89c12580 id: nil, name: nil, size: nil, created_at: nil, updated_at: nil, user_id: nil>imageカラムが存在しない

  def update
    @item.update(name: 'farao', image: 'nankanoatai', image_cache: 'nankanoatai', size: 'nankanoatai')
    redirect_to items_path, notice: '図鑑を更新しました'
  end

下記の感じでやればとりあえずエラーは回避できるかと

  def update
    @item.update(name: item_params[:name])
    redirect_to items_path, notice: '図鑑を更新しました'
  end

@MIDO-ruby7
Copy link
Owner Author

MIDO-ruby7 commented Jun 13, 2023

photosテーブルのimageカラム名あたりが怪しいかもです…

菅野さん有難うございます!すみません、コメントに気付くのが遅くて、カラム変更試す前になんとかなりました。カラムいじったらすぐだったかもしれない…😇

中井さんの最初のコメントの記事でとりあえずアソシエーション関連を見直してみようと思い、
accepts_nested_attributes_for :photosをitemモデルに定義
formのネストをf.fields_forで変更してparams側のネストも変えてあげたらいけました。良いのかよくわかんないですがとりあえずnew, editともに登録できるようになりました。

中井さん、コメント有難うございます!!参考になります😭、もう一回コードみてみます!

Itemはimage持たないように設計してると思うのですが、item_paramsそのまま渡しててimageカラムを更新しようとしてしまっているのが原因かと思います

下記の感じの処理が動いてしまっているがitemには#<Item:0x0000ffff89c12580 id: nil, name: nil, size: nil, created_at: nil, updated_at: nil, user_id: nil>imageカラムが存在しない

  def update
    @item.update(name: 'farao', image: 'nankanoatai', image_cache: 'nankanoatai', size: 'nankanoatai')
    redirect_to items_path, notice: '図鑑を更新しました'
  end

下記の感じでやればとりあえずエラーは回避できるかと

  def update
    @item.update(name: item_params[:name])
    redirect_to items_path, notice: '図鑑を更新しました'
  end

@MIDO-ruby7 MIDO-ruby7 merged commit 7bc3b4b into main Jun 13, 2023
@MIDO-ruby7 MIDO-ruby7 deleted the release0.0.7/item_edit_delete branch June 13, 2023 04:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants