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

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

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

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

Active Record

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

Q&A

解決済

1回答

4794閲覧

ActiveRecordの複合的なHas Many関係のテーブル情報取得について

hrc

総合スコア55

Ruby on Rails

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

Active Record

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

0グッド

0クリップ

投稿2016/06/23 23:31

編集2016/06/24 15:32

Ruby on Rails でActiveRecordを使っています。

例えば以下の様な6つのテーブルがあったとして

Area

  • AreaTranslation(has many・複数の翻訳された地域情報がある)
  • Restaurant(has many・複数の店舗情報がある)
    • RestaurantTranslation(has many・複数の翻訳された店舗情報がある)

このような関係性だった場合

Areaテーブルのid=1に紐づくRestaurantTranslationの情報(例:restaurantname)を取得するにはどのようにしたらいいでしょうか?

【追記】
実はErrorが出ていて、
Association named 'restaurant_translations' was not found on Area; perhaps you misspelled it?
となってしまいます。

URLでIDを指定しているので、それに紐付いたrestaurantとrestaurant情報が全部出力したい感じです。

ソースを提示します。Controllerはこちらです。

ruby

1class AreaController < ApplicationController 2 def index 3 @areas = Area.all 4 end 5 6 def show 7 @areas = Area.includes(:area_translations, :restaurants, :restaurant_translations).where(id: params[:id]) 8 end 9end

Modelはこちらです。

ruby

1class Area < ActiveRecord::Base 2 has_many :area_translations 3 has_many :restaurants 4end 5 6class Restaurant < ActiveRecord::Base 7 has_many :restaurant_translations 8 has_many :menus 9 has_many :reviews 10 11 belongs_to :areas 12 13end 14 15class RestaurantTranslation < ActiveRecord::Base 16 self.table_name = 'restaurant_translations' 17 belongs_to :restaurants 18 19 scope :with_lang , -> { where(lang: I18n.locale )} 20 21end 22 23class AreaTranslation < ActiveRecord::Base 24 belongs_to :areas 25 26 scope :with_lang , -> { where(lang: I18n.locale )} 27end 28

View(slim)はこちらです。

ruby

1table 2 thead 3 tr 4 th = t :restaurant_list_type 5 th = t :restaurant_list_name 6 th = t :restaurant_list_url 7 th = t :restaurant_list_genre 8 tbody 9 - @areas.each do |area| 10 tr 11 td = area.restaurants.restaurant_type 12 td = link_to area.restaurants.restaurant_translations.with_lang.first.restaurantname, (url_for controller:'restaurant', trailing_slash: true) + area.restaurants.id.to_s 13 td = link_to 'official', area.restaurants.url 14 td = area.restaurants.genre

Error内容はこちらです。
イメージ説明

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

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

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

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

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

guest

回答1

0

ベストアンサー

Ruby

1Area.includes(:area_translations, :restaurants, :restaurant_translations)

これで行けませんか?
where等で複合条件をつけて取得しようとすると、Arelを使って組むか、Scopeを使って設定しておいてやる必要があるかもしれませんが。

ソースが示されたので、それに従って変更したものは下記の通りです。

Ruby

1Area.includes([:area_translations, {restaurants: :restaurant_translations}])

投稿2016/06/24 06:05

編集2016/06/24 12:14
rifuch

総合スコア1901

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

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

hrc

2016/06/24 08:31

ありがとうございます!確認しますので少々お時間下さい。
hrc

2016/06/24 09:42

すみません、確認しましたが、Errorが出てしまいます。areaのid=1に紐づくものを一通り出したいというのが要望となります。表記の問題だとは思いますが、わからないのでご教示ください。
rifuch

2016/06/24 12:12

回答したときに、モデルのソースがなかったので、has_many関連がそのまま直にAreaについているものと思って回答してしまいました。 追記されたソースからだと、 Area.includes([:area_transrations, {restaulants: :restaurant_transrations}]) が正しいでしょう。 直接has_manyしているものは、配列として列挙し、入れ子になっているものはハッシュとして表現してあげれば、後はActiveRecordがよしなにしてくれます。
hrc

2016/06/24 13:28

ありがとうございます。残念ながら結果が同じですね。Areaテーブルのデータでないものを表示しようとしていることが原因かもです。エラー内容も掲出しておきます。
rifuch

2016/06/24 14:53

エラーはincludeのところで:area_translationsとすべき所を、:area_transrationsとしたために起こっているようですが・・・
hrc

2016/06/24 15:36

大変失礼しました!修正して、かつViewのarea.restaurantとなっていたところをarea.restaurantsに修正してやってみたところUndefined Methodになっていまいました。上記カラムは確実にrestaurantsテーブルに存在するんですが・・・ また、Controllerですが、 @areas = Area.includes([:area_translations, {restaurants: :restaurant_translations}]).where(id: params[:id]) としても大丈夫でしょうか?IDで引っ掛けたいので、どのようにしたらよいかご教示いただければ幸いです。何度もすみません。
rifuch

2016/06/24 16:01

おそらく、やりたい事はparams[:id]で指定された1件を取得する事でしょうから、 @area = Area.includes([:area_translations, {restaurants: :restaurant_translations}]).where(id: params[:id]).first で1件のみ取得し、ビューの方では不要なeachを呼ばずに利用するのが常套手段だと思います。 画面写真で提示されたエラーは、viewで発生していますが、実際の所、viewの中の@areas.eachがコールされたときに、ActiveRecordが実際のSQLを生成し、DBアクセス仕様としたときに発生しています。 ですから、実際のエラーは、Controllerのshowアクションで記述されている取得用のコードのところで発生しているのです。 画面写真で示されたエラーは、そこの部分(showアクションの@areas取得部分)で発生しており、そこにtypoがあるようです。 修正後に発生したエラーについても、情報を頂ければ何かアドバイス出来るかと思います。
hrc

2016/06/24 16:17

諸々恐れいります。実はAreaID:1に属するレストランを全件表示するということをやろうとして複数のテーブルを結合しておりました。 恐らくこれが問題だったのかなということで、area->area_translationとarea->restaurant->restaurant_translationの結合を分離して表示したところ思っていたように表示させることが出来ました。本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問