質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

1回答

3442閲覧

RailsでFormオブジェクトを使用した場合の、複数テーブルの編集・更新機能の実装方法について

momomo26964417

総合スコア0

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/09/13 08:04

Formオブジェクトを使用した複数テーブルの編集。更新機能の実装

ここに質問の内容を詳しく書いてください。
Formオブジェクトを使用し、複数テーブルの作成・削除機能は実装できましたが、編集がどうしてもうまく実装できません。どのように考え組み立てていけばいいのか、ご教授願いたいです。

  • テーブル設計
TableColumnTypeNotNull
itemspriceinteger
//numberinteger
//unit_priceinteger
//textstring
//userreference
tagsnamestring
item_tagitemreference
//tagreference
------------------------------------------
  • ActiveStorageを使用して、itemsにimageを保存できるようにしています。

model

ruby

1class Item < ApplicationRecord 2 belongs_to :user 3 has_many :item_tag_relations 4 has_many :tags, through: :item_tag_relations, dependent: :destroy 5 has_one_attached :image 6 7 def self.search(search, id) 8 if search != "" 9 Item.joins(:tags).where(tags: {name: "#{search}"} , user_id: id) 10 else 11 Item.where(user_id: id) 12 end 13 end 14 15end 16 17class Tag < ApplicationRecord 18 has_many :item_tag_relations 19 has_many :items, through: :item_tag_relations 20 21 validates :name, uniqueness: true 22end 23 24class ItemTagRelation < ApplicationRecord 25 belongs_to :item 26 belongs_to :tag 27end 28

routes

ruby

1#該当部分のみ表示 2resources :items, only: [:new, :create, :show, :destroy, :edit, :update] do 3 collection do 4 get 'tagsearch' 5 end 6 end 7

#### items controller

ruby

1def edit 2 @item = Item.find(params[:id]) 3end 4 5def update 6 @item = ItemsTag.new(update_item_params) 7 if @item.valid? 8 @item.update 9 return redirect_to user_path(current_user.id) 10 else 11 render "edit" 12 end 13end 14 15private 16 17def update_item_params 18 params.require(:items_tag).permit(:image, :price, :number, :unit_price, :text, :name).merge(user_id: current_user.id) 19 end 20

Fromオブジェクト

ruby

1class ItemsTag 2 3 include ActiveModel::Model 4 attr_accessor :image, :price, :number, :unit_price, :text, :name, :user_id 5 6 with_options presence: true do 7 validates :image 8 validates :price 9 validates :number 10 validates :unit_price 11 validates :name 12 end 13 14 def save 15 item = Item.create(image: image, price: price, number: number, unit_price: unit_price, text: text, user_id: user_id) 16 tag = Tag.where(name: name).first_or_initialize 17 tag.save 18 19 ItemTagRelation.create(item_id: item.id, tag_id: tag.id) 20 end 21 22 def update 23 item = Item.update(image: image, price: price, number: number, unit_price: unit_price, text: text, user_id: user_id) 24 tag = Tag.where(name: name).first_or_initialize 25 tag.save 26 27 ItemTagRelation.update(item_id: item.id, tag_id: tag.id) 28 end 29 30end

■■edit/update機能を実装中に以下のエラーメッセージが発生しました。

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

@item.imageがnilとなってしまう。

35: def update => 36: binding.pry 37: @item = ItemsTag.new(update_item_params) 38: if @item.valid? 39: @item.update 40: return redirect_to user_path(current_user.id) 41: else 42: render "edit" 43: end 44: end [1] pry(#<ItemsController>)> @item = ItemsTag.new(update_item_params) => #<ItemsTag:0x00007f9daf2a6c10 @name="ティッシュ", @number="4", @price="1200", @text="", @unit_price="300", @user_id=1> [2] pry(#<ItemsController>)> @item.image => nil

試したこと

当初controllerのeditアクションの定義を

ruby

1def edit 2 @item = ItemsTag.find(params[:id]) 3end

していたが、ItemsTagクラスにfindメソッドがないとのことから、現在の形に変更したものの
edit.html.erb遷移時にtagのnameの値が受け渡されず、imageもnilとなってしまった。
元の考え方から間違っている気がしますが、どのように改善すればいいのかわからなく、3日程悩んでいます。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。
Ruby on Rails 6.0.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

@item.image => nil 以前に????状態です

ItemTag の updateですが
item = Item.update(image: image, ) これは Itemの全てのデータを修正します。
ItemTagRelation.update(item_id: item.id, tag_id: tag.id)も同じく。
もし controllerの@item = ItemsTag.new( ) でこの ItemTagのupdateの結果を入れているつもりなら、戻り値は最後の式ItemTagRelation.update( ) の結果なので@itemはItemのインスタンスではないです。

さらに @item = ItemsTag.new( )なので、ItemTag の update は呼ばれません。未定義(つまりdefaultな) initialize の結果が戻ります。
つまり、@itemは ItemTag のインスタンスです。
initalize未定義なので全てのデータはnilです。
@item = ItemsTag.new.update( )という形にしましょう。

なお
tag = Tag.where(name: name).first_or_initialize tag.save
tag = Tag.find_or_create_by(name: name)で行けます。

ItemTagにfindが未定義なら定義すれば良いのです。
def find(id) Item.find(id) end
辺りでしょうか。

投稿2020/09/16 23:43

winterboum

総合スコア23360

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問