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

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

ただいまの
回答率

90.75%

  • Ruby

    7017questions

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

  • Ruby on Rails

    6737questions

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

  • Ruby on Rails 4

    2380questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Ruby(Ruby on Rails) ビューでのループの仕方について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 337

anvinon

score 30

開発環境

  • MacOS X 10.11 El Capitan
  • Ruby 2.3.1
  • Ruby on Rails 4.2.6

発生している問題

ビューで、ループの仕方がよくわからず、困っています。下記に出来るだけ詳しく書きましたので、わかる方いらっしゃれば、ご教示願います。

ゴール

この画像のような状態にしたいです。
イメージ説明
一番上にユーザーレビューという文字があり、その下に複数のレビューがあります。そして、レビューに複数のコメントがある状態です。

現状

以下のような状態で、コメントが表示されていません。また、「複数のレビューに、複数のコメント」という状態になっていません。

イメージ説明

ビューは以下のソースコードのようにしました。

# app/views/products/show.html.erb

<h2>ユーザーレビュー</h2>
<% if @review_all.nil? %>
  まだユーザーレビューはありません。
<% else %>
  <% @review_all.each do |r| %>
    ユーザー名:<%= @review_all.find(r).name %>
    レビュー文:<%= @review_all.find(r).text %>
    <% @review_all.each do |c| %>
      コメント:<%= @review_all.find(r).comments.find_by(id: c) %>
    <% end %>
  <% end %>
<% end %>

コントローラーは以下のとおりです。

# app/controllers/products_controller.rb

class ProductsController < ApplicationController

  def index
    @product_all = Product.all
  end

  def new
    @product_new = Product.new
    @review =Review.new
   end

  def create
    Product.create(product_params_create)
    redirect_to :action => "index"
  end

  def show
    @product = Product.find(params[:id])
    session[:cart] ||= {}
    session[:cart]["#{params[:id]}"] = Product.find(params[:id])
    @review_new = Review.new
    session[:product_show_id] = params[:id]
    @review_all = Review.all
    @comment_all = Comment.all
  end

  def add
    if session[:item] == nil then
      session[:item] ||= {}
      session[:item]["#{params[:id]}"] = params[:item]
    else
      session[:item]["#{params[:id]}"] = params[:item].to_i + session[:item]["#{params[:id]}"].to_i
    end
  end


  def content
  end

  def destroy
    product = Product.find(params[:id])
    product.destroy
  end

  def edit
    @product_edit = Product.find(params[:id])
  end

  def update
    @product_update = Product.find(params[:id])
    @product_update.update(product_params_update)
    redirect_to :action => "index"
  end

  def search
    @products = Product.all
    if params[:description].present?
      @products = @products.get_by_description params[:description]
    end
  end

private
  def product_params_create
    params.require(:product).permit(:price, :description, :image)
  end

  def product_params_update
    params.permit(:price, :description, :image)
  end

end

モデルは以下のとおりです

# app/models/comment.rb

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :review
end
# app/models/product.rb

class Product < ActiveRecord::Base
  mount_uploader :image, ImageUploader
  #ユーザー名による絞り込み
  scope :get_by_description, ->(description) {where("description like ?", "%#{description}%")}
  has_many :reviews
end
# app/models/review.rb

class Review < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
  has_many :comments
end
# app/models/user.rb

class User < ActiveRecord::Base
  has_secure_password
  validates :name, presence: true, :uniqueness => true
  validates :email, presence: true, :uniqueness => true
  has_many :reviews 
  has_many :comments
end


データベースのテーブルの構造は以下の状態になっています。

psgr_db=# select * from users;
id | name |              email               |                       password_digest                        |         created_at         |         updated_at         
----+------+----------------------------------+--------------------------------------------------------------+----------------------------+----------------------------
71 | a    | ここはメールアドレスのため消去   | $2a$10$p5DiQ7Bh1zOg71OQdOBBnuVTiuszmrS/sRS9rx8Fr2uAJFmYQZFVy | 2017-06-27 00:49:49.70169  | 2017-06-27 00:49:49.70169
72 | b    | ここはメールアドレスのため消去 | $2a$10$bt4vEi9awOMxeMBlo2S/kOVYtHibapImXf4oo/kdxzMvf8JQJgCk6 | 2017-06-27 04:03:42.885492 | 2017-06-27 04:03:42.885492
(2 rows)

psgr_db=# select * from products;
id     | price | description |         created_at         |         updated_at         |    image     
-----------+-------+-------------+----------------------------+----------------------------+--------------
980190962 |       |             | 2017-06-17 02:59:35        | 2017-06-17 02:59:35        | 
298486374 |       |             | 2017-06-17 02:59:35        | 2017-06-17 02:59:35        | 
980190963 |     1 | 青い時計    | 2017-06-17 05:52:30.865063 | 2017-06-17 05:52:30.865063 | watch025.png
980190964 |     2 | 白い時計    | 2017-06-17 05:53:00.457151 | 2017-06-17 05:53:00.457151 | watch001.png
(4 rows)

psgr_db=# select * from comments;
id | user_id | review_id |               text               |         created_at         |         updated_at         
----+---------+-----------+----------------------------------+----------------------------+----------------------------
23 |      72 |        19 | 強度がどれくらいなのかが気になる | 2017-06-29 22:37:38.241337 | 2017-06-29 22:37:38.241337
24 |      72 |        19 | 強度は結構ありますね             | 2017-06-29 22:47:39.277646 | 2017-06-29 22:47:39.277646
(2 rows)

psgr_db=# select * from reviews;
id | user_id | name |             text             |         created_at         |         updated_at         | product_id 
----+---------+------+------------------------------+----------------------------+----------------------------+------------
19 |      72 | b    | 作りがしっかりとした時計です | 2017-06-29 22:35:44.657063 | 2017-06-29 22:35:44.657063 |  980190964
(1 row)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

色々ツッコミどころ満載ですね。
とりあえず、一回公式チュートリアルをやったほうがいいかもしれません。

 <% @review_all.each do |c| %>
      コメント:<%= @review_all.find(r).comments.find_by(id: c) %>
    <% end %>


 <% @comment_all.each do |c| %>
      コメント:<%= @review_all.find(r).comments.find_by(id: c) %>
    <% end %>


にすればとりあえず動きそうですが
全然Railsぽくなくスマートではないので
下記のようにしてみてください。
※本題と外れますが@review_allがnilになることはありません

# app/views/products/show.html.erb

<h2>ユーザーレビュー</h2>
<% if @review_all.blank? %>
  まだユーザーレビューはありません。
<% else %>
  <% @review_all.each do |r| %>
    ユーザー名:<%= r.name %>
    レビュー文:<%= r.text %>
    <% r.comments.each do |c| %>
      コメント:<%= c.text  %>
    <% end %>
  <% end %>
<% end %>


また、上記だけでも動きますが
show を下記のようにするとReviewに対するコメントをあらかじめ取得するのでスピードアップが測れます。

  def show
    @product = Product.find(params[:id])
    session[:cart] ||= {}
    session[:cart]["#{params[:id]}"] = Product.find(params[:id])
    @review_new = Review.new
    session[:product_show_id] = params[:id]
    @review_all = Review.joins(:comments).references(:comments)
  end

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/03 16:25

    moke様

    こちらでもご回答くださり、ありがとうございます。Railsチュートリアルは8章までしかやっていないので、続きもやります。

    また、頂いたスピードアップのご回答も、勉強します。ありがとうございました。ベストアンサーとして選ばせて頂きます。

    キャンセル

  • 2017/07/03 16:39

    チュートリアル8章までやったなら、最後までやっても、絶対必要なのはこの内容だけですね
    一度現在のappを作り終えてから再度、チュートリアルを見る方が勉強になるかもしれません。
    そこはご自由にw

    ここでいうスピードアップとはRailsとDBの接続回数を減らすという意味です。
    @review_all = Review.joins(:comments).references(:comments)
    commentsがないreviewがある場合joinsではなくincludesのがいいです。
    rails5だとleft_joinsができてさらにスピードアップが測れます。

    キャンセル

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

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7017questions

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

  • Ruby on Rails

    6737questions

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

  • Ruby on Rails 4

    2380questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。