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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Haml

Haml(HTML abstraction markup language)は、HTML/XHTMLを効率的に記述するためのマークアップ言語および記法です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

2390閲覧

NoMethodError in BooksController#create エラーを解決し、投稿機能を実装したい

ntk__7__ksn

総合スコア14

Haml

Haml(HTML abstraction markup language)は、HTML/XHTMLを効率的に記述するためのマークアップ言語および記法です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2020/09/05 09:32

編集2020/09/05 11:48

#前提
()はカラムです。

booksテーブル(name, price, author, image, user_id)
categoriesテーブル(name)
book_categoriesテーブル(book_id, category_id)   ◀︎ 中間テーブル

#実現したいこと

投稿機能を実装できるようにしたい
#エラーメッセージ

NoMethodError in BooksController#create undefined method `category_id' for #<Book:0x00007fe0616824e8> Did you mean? category_ids category_ids= Extracted source (around line #14): def create Book.create(book_params) if Book.create redirect_to root_path else

#該当のソースコード
books_controller.rb

class BooksController < ApplicationController before_action :move_to_index, except: [:index, :show] before_action :set_book, only: [:edit, :show] def index @books = Book.all.order(created_at: :DESC) end def new @book = Book.new end def create ActiveRecord::Base.transaction do book = Book.create!(book_params) BookCategory.create!(book: book, category_id: params[:category]) end redirect_to root_path rescue ActiveRecord::RecordInvalid => e render :new end def destroy book = Book.find(params[:id]) book.destroy if !book.save redirect_to root_path end end def show end def edit end def update book = Book.find(params[:id]) book.update(book_params) if book.save redirect_to book_path(book.id) else render :index end end private def book_params params .require(:book).permit(:name, :price, :author, :image) .merge(user_id: current_user.id) end def set_book @book = Book.find(params[:id]) end def move_to_index unless user_signed_in? redirect_to action: :index end end end

new.html.haml
投稿する画面のviewです。
関係あるかわかりませんが載せておきます。

%header = render partial: 'header2.html.haml' %p.title 登録 .save .item = form_with model: @book, local: true do |f| %ul.contents %li.content .image 表紙 = f.text_field :image, placeholder: "画像URL", required: "", class: "default" %li.content = f.label :category, "カテゴリー" = f.collection_select :category, Category.all, :id, :name, include_blank: "カテゴリを選択してください" %li.content .name 本の名前 = f.text_field :name, placeholder: "例)ワンピース", required: "", class: "default" %li.content .author 著者 = f.text_field :author, placeholder: "例)尾田栄一郎", required: "", class: "default" %li.content .price 値段(税込み) = f.text_field :price, placeholder: "例)500", required: "", class: "default" %em 円 .btn = f.submit "登録", class: "btn-newBook" %footer = render partial: 'footer.html.haml'

book.rb

class Book < ApplicationRecord validates :name, presence: true validates :price, presence: true validates :image, presence: true validates :author, presence: true belongs_to :user has_many :categories has_many :categories, through: :books_categories end

category.rb

class Category < ApplicationRecord validates :name, presence: true has_many :books has_many :books, through: :books_categories end

book_category.rb

class BookCategory < ApplicationRecord validates :book_id, presence: true validates :category_id, presence: true belongs_to :book belongs_to :category end

user.rb

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end

application_record.rb

class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end

#自分で調べたことや試したこと
・ 下記category_idの記述の仕方が違うと判断し、検索して出てきた記述を書いてみたが全て違った

params.require(:book).permit(:name, :price, :author, :image, :user_id, { category_id: [] })

・ booksテーブルにcategory_idカラムを追加しbooks_controllerの privateのpermitの()の中にcategory_idを追加すると投稿機能は実装できるが、book_categoriesテーブルには何も反映されない。

・ user_idをpermitの()の中に記述しているがbinbing.pryで確認したところuser_idが記述されていない為これも関係しているのか

49: def book_params

50: binding.pry
51: params.require(:book).permit(:name, :price, :author, :image, :user_id, { category_id: [] })

[1] pry(#<BooksController>)> params.require(:book).permit(:name, :price, :author, :image, :user_id, { category_id: [] })

Unpermitted parameter: :category
=> <ActionController::Parameters {"name"=>"ロマンチカクロック2", "price"=>"500", "author"=>"槙ようこ", "image"=>"https://dosbg3xlm0x1t.cloudfront.net/images/items/9784088672724/1200/9784088672724.jpg"} permitted: true>

解決法がわかる方がいらっしゃいましたら教えていただけると助かります。

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

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

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

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

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

guest

回答1

0

ベストアンサー

ruby

1 def create 2 ActiveRecord::Base.transaction do # book と book_category どちらも保存できなければエラーに 3 book = Book.create!(book_params)# transaction を rollback するため ! 4 BookCategory.create!(book: book, category_id: params[:category]) # 明示的に作る 5 end 6 redirect_to root_path 7 rescue ActiveRecord::RecordInvalid => e # 必要に応じて他の例外も 8 render :new 9 end 10 11 private 12 13 def book_params 14 params 15 .require(:book).permit(:name, :price, :author, :image }) 16 .merge(user_id: current_user.id) # user_id はパラメータで入力せずに現在のユーザーに対して 17 end

でしょうか、 strong parameter 使って暗黙的にやる方法もありますが、
わかりやすさを重視するとやることをちゃんと書くべきなのかと思いました

追記

book.rb

validates :category_id, presence: true

が不要に思いましたmm
category_id というカラムが有るのであれば別ですが

投稿2020/09/05 10:01

編集2020/09/05 11:40
unhappychoice

総合スコア1531

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

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

ntk__7__ksn

2020/09/05 10:36 編集

コメントありがとうございます。 教えて頂いたものを記述してみましたが、エラー文に変化はなく解決できませんでした。 エラー文⬇︎ NoMethodError in BooksController#create undefined method `category_id' for #<Book:0x00007fe05eb23f68> Did you mean? category_ids category_ids= Extracted source (around line #15): def create ActiveRecord::Base.transaction do book = Book.create!(book_params BookCategory.create!(book: book, category_id: params[:category]) end
ntk__7__ksn

2020/09/05 10:38

.mergeのなかに、book_categoryをどこかに関連付けするような記述をしないといけないのでしょうか?
unhappychoice

2020/09/05 10:42

現状のコード全文を掲載お願いしますmm
ntk__7__ksn

2020/09/05 10:47

コードはcontrollerで合っていますでしょうか? 合っていましたら、修正し掲載しました。 よろしくお願い致します。
unhappychoice

2020/09/05 10:51

ありがとうございます、model も掲載良いでしょうかmm
ntk__7__ksn

2020/09/05 11:05 編集

現在記述してあるものを該当コードに掲載しました。 よろしくお願いし致します!
ntk__7__ksn

2020/09/05 12:02

修正しました。 エラーは解消出来ました!! ありがとうございます! ですがデータが保存できなく、データを入力し登録ボタンを押すとリロードしたような感じで入力したものが消えるというような感じになってしまいました。 こちらはcontrollerの記述を変更した方が良いでしょうか?
unhappychoice

2020/09/05 12:05

例外が起きている気がするので、 ``` rescue ActiveRecord::RecordInvalid => e # 必要に応じて他の例外も p e p e.messages render :new end ``` として調べる必要がありそうです
ntk__7__ksn

2020/09/05 12:13 編集

ありがとうございます。 質問なのですが、 p e.messages のpとは何の事を指しているのでしょうか? 初めてみた記述でどのような記述をして何を調べたらいいのか分からないので教えて頂けると助かります。 よろしくお願いし致します。
ntk__7__ksn

2020/09/05 13:00

一通り読み検索して使い方など調べてみたのですが、いまいちよく分からずで p e.messages のmessagesのところを登録時に入力する文字を入力すれば良いのでしょうか? 例えば画像のURLを登録する時は p e.https://images-na.ssl-images-amazon.com/images/I/71WC61yAmBL.jpg こういう感じでURLを書くという感じなのでしょうか? それともimageと書けば良いのでしょうか?
ntk__7__ksn

2020/09/05 13:02

gemを導入して記述するものでしょうか?
ntk__7__ksn

2020/09/06 09:31

BookCategory.create!(book: book, category_id: params[:category]) # 明示的に作る end redirect_to root_path rescue ActiveRecord::RecordInvalid => e # 必要に応じて他の例外も render :new の行を削除し、 if book.save redirect_to root_path else render :new end に変更したら保存出来るようになりました。 消してしまった部分が必要なのかはまだわかりませんが今は消した状態で実装してみようと思います。 ありがとうございました! 助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問