如何使用has_many关联从数据库检索数据

时间:2019-07-01 11:59:34

标签: ruby-on-rails ruby-on-rails-5 has-many

我有

  

消息表

  

message_pictures

表(它属于消息表),我要做的是从

检索每一个消息图片(如果有)。
  

message_controller

我该怎么做。我已经上网冲浪了,但是却很少得到解释。

这是消息类别(模型)

class Message < ApplicationRecord
  belongs_to :user
  has_many :message_pictures, dependent: :destroy
  accepts_nested_attributes_for :message_pictures
end

这是message_pictures类(模型)

class MessagePicture < ApplicationRecord
  belongs_to :message, optional: true
  mount_uploader :message_pictures, PictureUploader
end

这是message_controller类的索引方法

def index
    @user = User.find(current_user.id)#414, 449, 494
    @messages = @user.messages.paginate(page: params[:page])
    #@messages = @messages.message_pictures.paginate(page: params[:page])
end

您可以看到index方法的第4行,以了解我的挖矿方法,但它不起作用

1 个答案:

答案 0 :(得分:3)

我相信您需要的是has_many ... :through

app / models / user.rb

class User < ApplicationRecord
  # ...
  has_many :messages, dependent: :destroy
  has_many :message_pictures, through: :messages
end

app / controllers / messages_controller.rb

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)
    @messages = @user.messages.paginate(page: params[:page])
    @message_pictures = @user.message_pictures
  end
end

has_many ... :through简化了通过“ SQL JOINS”检索“嵌套”子记录的过程,通常,您可以通过更长(更明确的方式)来进行检索,如下所示(也可以):

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)
    @messages = @user.messages.paginate(page: params[:page])
    @message_pictures = MessagePicture.joins(message: :user).where(
      messages: { # <-- this needs to be the table name, and not the association name, and is why it is in plural form
        users: { # <-- this needs to be the table name, and not the association name, and is why it is in plural form
          id: @user.id
        }
      }
    )
  end
end

更新:替代解决方案

回想一下您的问题,我觉得您只想要@message_pictures对应@messages而不是全部@user.messages的原因,因为我注意到您已经对这些消息进行了分页。我将改为这样:

app / controllers / messages_controller.rb

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)

    # the `includes` here prevents N+1 SQL queries, because we are gonna loop
    # through each `message_picture` in each `message` record (see index.html.erb below)
    @messages = @user.messages.includes(:message_pictures).paginate(page: params[:page])
  end
end

app / views / messages / index.html.erb (示例)

<h1>Messages:</h1>
<% @messages.each do |message| %>
  <section>
    <h2>Message:</h2>
    <p><%= message.content %></p>

    <h3>Message Pictures:<h3>
    <div>
      <% message.message_pictures.each do |message_picture| %>
        <% message_picture.message_pictures.each do |message_picture_attachment| %>
          <%= image_tag message_picture_attachment.url.to_s %>
        <% end %>
        <br>
      <% end %>
    </div>
  </section>    
<% end %>

^上面假设MessagePicture正在使用carrierwave。附言在我看来,您定义模型的方式有问题,因为您的message有很多message_pictures,而每个message_picture也有很多附件message_picture载波附件(假设您使用的是载波的“多文件”上传设置,因为您使用的是mount_uploader :message_pictures, PictureUploader而不是mount_uploader :message_picture, PictureUploader。我认为模型问题是因为这样的:message <{{1 }} <message_pictures,但是(取决于您的用例),它可能应该类似于message_pictures attachments <message-message_pictures,或者仅仅是{{1} } <{message_picture attachment