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

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

新規登録して質問してみよう
ただいま回答率
85.35%
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の基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Q&A

解決済

1回答

549閲覧

外部キーを設定した他のモデルのデータをviewに表示する方法[showアクション]

raurauji

総合スコア13

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の基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

0グッド

0クリップ

投稿2020/04/28 04:45

前提・実現したいこと

料理のレシピを管理するアプリを作っています。cookモデルを親、materialモデルを子としています。二つを紐付けてデータを登録するところまでは出来たのですが、showで表示する際にエラーが発生して詰まっています。

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

ActiveRecord::RecordNotFound in CookController#show Couldn't find Material without an ID

該当のソースコード

controller

1def new 2 @cook = Cook.new 3 @cook.materials.build 4 @cook.works.build 5end 6 7def show 8 @cook = Cook.find(params[:id]) 9 @materials = Material.find(params[:cook_id]) 10end

haml

1= @cook.title 2= @cook.description 3= @materials.material1

material

1class CreateMaterials < ActiveRecord::Migration[5.2] 2 def change 3 create_table :materials do |t| 4 t.string :material1 5 t.string :material2 6 t.string :material3 7 t.string :material4 8 t.string :material5 9 t.string :material6 10 t.string :material7 11 t.string :material8 12 t.string :material9 13 t.string :material10 14 t.string :material11 15 t.string :material12 16 t.string :material13 17 t.string :material14 18 t.string :material15 19 t.string :material16 20 t.string :material17 21 t.string :material18 22 t.string :material19 23 t.string :material20 24 25 t.references :cook, index: true, foreign_key: true 26 27 t.timestamps 28 end 29 end 30end

試したこと

@materials = Material.find(params[:cook_id])を消すと@cookのtitleとdescriptionはちゃんと表示されます。また、@cookから直接取り出せるのではないかと思い、@cook.material1などとviewに書いてみましたがダメでした。

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

追加で補足していきます。

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

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

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

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

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

guest

回答1

0

ベストアンサー

…すいません、あってるかどうかわかりませんが…。
私も非エンジニアのトウシロウですので…。

まず、今回のエラー、解消自体は簡単です。以下を修正してください。

controller

1def show 2 @cook = Cook.find(params[:id]) 3 @materials = Material.find_by(cook_id: params[:cook_id]) 4end

これだけです。変更点はfindfind_byにしただけですね。
重要なのは**findメソッドとfind_byメソッドの役割の違いです。**
ご自身で調べたほうがいいと思いますのであえてここでは記述しませんが、カッコの中、引数の部分の記述が違いますね。これによってこの2つのメソッドは全く別の振る舞いをしてくれるわけです。
これでrauraujiさんの今回の問題は解決ですね、表面上は

ただ今回のお話、もっと重要な問題が隠れています。
結論を申し上げます。
Active Recordのシステム、特に関連付けについて大きな誤解をされています。

…ごめんなさい。私もこの部分の理解には相応の時間を要しましたので、非難するつもりは全くありません。ただ、ここは明確にしておかないと沼から抜けられない用に思いました(経験者談)ので…。平にご容赦ください。

とりあえず、「動いてほしい多分あってると信じたい苦しいときの神頼みコード」は以下のような形になると思います。

Materials

1class CreateMaterials < ActiveRecord::Migration[5.2] 2 def change 3 create_table :materials do |t| 4 t.string :material_name, null: false, default: "" 5 t.integer :procedure, null: false, default: 0 6 7 t.references :cook, foreign_key: true 8 9 t.timestamps 10 end 11 end 12end

CookModel

1class Cook < ApplicationRecord 2 has_many :materials 3end

MaterialModel

1class Material < ApplicationRecord 2 belongs_to :materials 3end

controller

1def show 2 @cook = Cook.find(params[:id]) 3 @materials = @cook.materials.order("procedure ASC") 4end

おそらく何が書いてあるのかイメージがしにくいと思います。
そんなrauraujiさんには**Railsガイドを読み込むことを強く推奨します。**
また、ここで触れた内容は**Active Record の関連付け**という部分に詳細な説明が掲載されています。
こんなポンコツの説明と比較するのもおこがましい、明瞭な記述です。
感覚的にまとめるなら、どのデータがどのデータにぶら下がっているのかっていうイメージを必要なところに書こうねといったところでしょうか。

例えば今回であれば、料理のレシピはたくさんの手順を持っていますよね。ですから、このイメージを文章にするとCook has many materials. また、Materials belongs to cook. になるわけです。
modelを見てみるとそのイメージが書いてありますよね。
また、こんな作りにするとfindとかfind_byはいらなくなって、whereが日の目を見ることになります。
が、これはまた別のお話…ということで。

さて、ここまでの説明で薄々お気づきとは思いますが、**外部キー制約云々はこのあたりの関連性を理解した後のお話で、今回の問題とは無関係です。**やらないほうがいいですが、外部キーってなくても動きますし…。

ということで、まずはActive Recordを見直そうというお話でした。
長々と書いてますが、所詮は素人に毛が生えたような人間の戯言です。
情報の正確性は全く担保できませんので、必ずご自身で情報収集をお願いします。
rauraujiさんのお力になれていれば幸いです。
長文失礼しました。

追伸:Ruby及びRailsガチ勢の皆様。浅瀬にも入らず砂山を作っているような小生の発言、問題がありましたらぜひ、ボッコボコのタコ殴りにし糾弾した上で、修正いただけますと幸いです。よろしくお願いいたします。

投稿2020/04/28 21:21

take77

総合スコア130

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

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

raurauji

2020/04/29 08:57

とても丁寧に回答していただきありがとうございます!! material.rbとcook.rbには一応アソシエーションを書いていたのですが、これがどこで役に立つものかをあまり意識せずに外部キーだけで関連付けさせようとしていたみたいです。 少しばかりですが、ActiveRecordに関する知識が深まった気がします。今後もActiveRecordの理解に注力していこうと思います!!
raurauji

2020/04/29 09:02

一つ質問なのですが、外部キーを使わずにwhereでデータを取得する際は、どのような記述になるのでしょうか?
take77

2020/04/30 18:38

取得の方法自体は変わりません。 外部キー制約というのは、そもそも「データベースの安全性を担保するための制約」ですので…。 データベース(railsの場合はmigration)のindexの貼り方を変更すれば制約は外れます。 ただし、「親のidが取得できないことによる謎のエラー」的なものが発生したり色々と問題が出る…んだったと思います。 違ってたらすいません…
raurauji

2020/05/03 10:17

なるほど!丁寧に説明していただき本当にありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問