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

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

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

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

Haml

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

Ruby on Rails

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1029閲覧

【初学者】RailsでDBから他テーブルの特定のレコードのカラムを取り出し表示させたい

RF18CHAMPION

総合スコア6

Ruby on Rails 5

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

Haml

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

Ruby on Rails

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/05/10 22:57

前提・実現したいこと

前提

ご覧いただきありがとうございます。現在、railsで車メーカーとそれに紐づく車種のそれぞれテーブルを用意しています。
CarmakersテーブルとCarsテーブルは1対多のリレーションになっています。
Carmakersテーブルでは、maker(車メーカー名)というカラムが存在しています。
Carsテーブルでは、car_type(車種名)、carmaker_idというカラムが存在しています。

実現したいこと
  • Carmaker/index(車メーカーの一覧ページ)において、それぞれの車メーカーに紐づいた車種名の中で、直近に登録された車種のみを表示させたいです。

わかっていること

  • carmaker.carsという記述で車メーカーに紐づく全ての車種の情報は取得できる
  • それをeach文で展開してcar.car_typeとすると、車メーカーに紐づく全ての車種名が表示できる

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

まず、上記のeach文での展開後にcar.lastと、最後のレコードのみを取得したいという意味で記述すると、no method error 'last'とエラーが出る。(これに関してはcarが配列ではないのでlastというメソッドは適用できないという記事を見つけることはできました)

次に、carmaker.cars.lastと、車メーカーに紐づく全ての車種の最後のレコードという意味で記述すると、#Car:0x00007f8229c7f3a0というようにレコードの情報全てが表示されます。
そこで、carmaker.cars.last.car_typeと、そのレコードの中のcar_typeというカラムの情報のみを表示させたいという意味で記述すると、下記のエラーが表示されます。(下記コードのhtmlでの最終行)

NoMethodError in Carmakers#index undefined method `car_type' for nil:NilClass

該当のソースコード

ruby

1.container 2 .row.row-cols-1.row-cols-md-1 3 - @carmakers.each do |carmaker| 4 .col-md-3 5 .card 6 = image_tag "#{carmaker.image}", class: "card-img-top", size: '320x400' 7 .card-body.text-white.bg-dark 8 %h3.card-title 9 = link_to carmaker.maker, carmaker_path(carmaker), class: "card-title-title" 10 %p.card-text 11 = carmaker.explanation 12 .card-footer.text-white.bg-dark 13 %p.card-createdat 14 = carmaker.cars.last.car_type

ruby

1 2class CarmakersController < ApplicationController 3 def index 4 @carmakers = Carmaker.includes(:cars) 5 end 6

試したこと

  • 該当レコード一つを取得することはできる
  • 該当カラムの一覧表示はすることができる
  • しかしながら、該当レコードの特定のカラム(今回ではcar_type)の一つ(今回では直近に登録された、つまり最新のcreated_at)表示させることができない
拙い文章でわかりにくいところもあるかと思いますがぜひご教授のほどよろしくお願いいたします。

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

rails5.2.3

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

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

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

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

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

guest

回答1

0

ベストアンサー

def index にて
@carmakers = Carmaker.includes(:cars).order("cars.created_at desc")

としておき、
= carmaker.cars.first&.car_type
でよいかと。
元々のでもほぼ良いのですが、carmaker.cars の並びがcrated_at順で有るかどうか保証がないので、orderをつけました。
もとのでエラーがでたのは、carsが登録されていないメーカーがあるのでは?と思われます。
その対策が first& の & です

投稿2020/05/10 23:45

winterboum

総合スコア23567

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

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

RF18CHAMPION

2020/05/10 23:56

コメントありがとうございます。 まさしくcarmakerに紐づいたcarのcar_typeのcreated_atの最新のものを表示させられました。 最終的にはview側で, = carmaker.cars.order("cars.created_at desc").first&.car_type と記載することで、carmakerの表示順はidの順番のままで、carのcar_typeのcreated_atの最新順にし(orderメソッド)その一つ(first)を取得することができました。 まさに欲しかった回答をスピーディーに、簡潔に、そして的確にご教授くださりありがとうございます。もう一度自分の中で咀嚼して知識定着を図りたいと思います。 今回は本当にありがとうございました!
winterboum

2020/05/11 12:58

最終的にはview側で, = carmaker.cars.order("cars.created_at desc").first&.car_type これはやめたほうが良いです。 1+N問題でしらべてみてください。
RF18CHAMPION

2020/05/11 13:21

コメントへの返信ありがとうございます。 つまりこの記載方法だとcarの情報を取り出す際、レコードの数だけSQLを発行してしまうという認識でよろしいでしょうか(コントローラーで@carmakers = Carmaker.includes(:cars)と記載していますが、、、)? 上記の認識の前提で、htmlを、 carmaker.includes(:cars).order("cars.created_at desc").first&.car_type と変更したところ、 undefined method `includes' for #<Carmaker:0x00007fc0a1cd1888> というエラーが出ました。 調べてみるとincludesメソッドはモデルに対してのメソッドであるとの記事を発見しました。 ただ今回に関しては、各車メーカー(carmaker)に紐づく車種(つまりcarmaker.cars)として記載しなければならず、includesメソッド等を活用してN+1問題を独自に解決することができませんでした、、 もしヒント等ご教授いただけましたら助かります、、
winterboum

2020/05/11 20:36

私の回答はそこを考慮しています。 それでは動かなかった?
RF18CHAMPION

2020/05/12 00:31

確認ありがとうございます。 現状は、 <carmaker_controller.rb> def index @carmakers = Carmaker.includes(:cars) end <index.html.haml> = carmaker.cars.order("cars.created_at desc").first&.car_type という記述で期待通りの挙動が確認できています。 今回指摘されたN+1問題を解決するためにご提案されたincludesメソッドを用いると、 <carmaker_controller.rb> def index @carmakers = Carmaker.includes(:cars) end <index.html.haml> = carmaker.includes(:cars).order("cars.created_at desc").first&.car_type と書き換えると、 NoMethodError in Carmakers#index undefined method `includes' for #<Carmaker:0x00007fc09f5fceb0> というエラーが確認できます。 コントローラー内でincludesメソッドをすでに使っているのでN+1問題は解決されてはいないのでしょうか?
winterboum

2020/05/12 02:21 編集

>コントローラー内でincludesメソッドをすでに使っているのでN+1問題は解決されてはいないのでしょうか? これはlogをみて確認頂くのが確実ですが、controllerでの式と(orderが加わることに依って)ことなるSQLになりますから、読みなおしている可能性があります。 >と書き換えると、 なぜ書き換えるのですか? orderはすでにcontrollerでの式でかかっているので不要です。 回答のままだとなにか不都合がでました?
RF18CHAMPION

2020/05/12 02:32

早速の返信ありがとうございます。 回答のままだと不都合はでませんでした。 私の勘違いだと思われるのですが、 >最終的にはview側で, = carmaker.cars.order("cars.created_at desc").first&.car_type これはやめたほうが良いです。 というご指摘をいただいたので、更にビュー側のコードの修正が必要なのかと思いましたので、htmlにおいてもN+1問題の解消をしなければならないと思い、includesメソッドを記述してみた、という次第です。 そもそもコントローラーでincludesメソッドを記述しているので、既にN+1問題は解消済み、故に、 = carmaker.cars.order("cars.created_at desc").first&.car_type という記述は変更する必要はないという解釈で合っていますでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問