【问题标题】:Why does my Rails 5 application print twice each record?为什么我的 Rails 5 应用程序每条记录打印两次?
【发布时间】:2017-06-25 09:17:09
【问题描述】:

这是一个 Rails 管理应用程序,同时也是一个 API。当我调用 myroot/api/v1/users 时,每条记录都会得到两次。

这是我的用户模型类:

class User < ActiveRecord::Base
  devise :database_authenticatable, :recoverable,
         :trackable, :validatable, :registerable,
         :omniauthable

  include DeviseTokenAuth::Concerns::User
  has_many :records
end

这是我的 Record 模型类:

class Record < ApplicationRecord
  belongs_to :user
  has_attached_file :audio,
                      :url => "/assets/:class/:id/:attachment/:style.:extension",
                      :path => ":rails_root/public/assets/records/:id/:style/:basename.:extension"
  validates_attachment_presence :audio
  validates_attachment_size :audio, :less_than => 3.megabytes
  validates_attachment_content_type :audio, :content_type => [ 'audio/mpeg',  'audio/mp3' ]

end

这是我的控制器用户类:

class Api::UsersController < Api::ApiController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
      # users = User.all
      # render json: users.to_json(except: [:id, :user_id, :email, :nickname])
      users = User.joins(:records)
       render json: users.to_json(only: [:id, :user_id, :email, :nickname], 
       include: {records: {only: [:record_id, :geolocation, :audio_file_name, :audio_content_type]}})
  end

  def show
      user = User.find(params[:id])
      render json: user.to_json(except: [:id, :user_id, :email, :nickname])
  end
end 

这是 JSON 结果:

[
    {
        "id": 4,
        "nickname": null,
        "email": "ricardope@gmail.com",
        "records": [
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Probe_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            },
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Selendis_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            }
        ]
    },
    {
        "id": 4,
        "nickname": null,
        "email": "ricardope@gmail.com",
        "records": [
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Probe_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            },
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Selendis_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            }
        ]
    },
    {
        "id": 6,
        "nickname": null,
        "email": "gabriela@gmail.com",
        "records": [
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Carrier_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            },
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Zealot_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            }
        ]
    },
    {
        "id": 6,
        "nickname": null,
        "email": "gabriela@gmail.com",
        "records": [
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Carrier_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            },
            {
                "geolocation": "-12.0858307,-76.9795114,17",
                "audio_file_name": "StarCraft_2_-_Zealot_Quotes.mp3",
                "audio_content_type": "audio/mpeg"
            }
        ]
    }
]

这是日志:

Processing by Api::UsersController#index as */*
  User Load (0.2ms)  SELECT `users`.* FROM `users` INNER JOIN `records` ON `records`.`user_id` = `users`.`id`
  Record Load (0.2ms)  SELECT `records`.* FROM `records` WHERE `records`.`user_id` = 4
  CACHE Record Load (0.0ms)  SELECT `records`.* FROM `records` WHERE `records`.`user_id` = 4  [["user_id", 4]]
  Record Load (0.3ms)  SELECT `records`.* FROM `records` WHERE `records`.`user_id` = 6
  CACHE Record Load (0.0ms)  SELECT `records`.* FROM `records` WHERE `records`.`user_id` = 6  [["user_id", 6]]
Completed 200 OK in 97ms (Views: 0.3ms | ActiveRecord: 3.4ms)

【问题讨论】:

  • 尝试将users = User.joins(:records)更改为users = User.all
  • 现在像魅力一样工作。谢谢 :)!!。但是,你知道为什么会这样吗?我对这种语言很陌生。
  • 我会解释的。也可以尝试User.includes(:records) 并检查它是否工作
  • 也适用于 'users = User.joins(:records)'。再次感谢。
  • 你能在记录表中检查任何记录具有相同的user_id吗?

标签: ruby-on-rails ruby rails-activerecord ruby-on-rails-5 rails-api


【解决方案1】:

说明

users = User.joins(:records)

以上活动记录查询触发usersrecords 表之间的INNER JOIN 查询。这意味着它将从两个表中获取所有记录,因为没有 where 子句。

输出将是来自users 表或records 表的总行数,哪一个是最高的。

这就是您获得users 表重复记录的原因。

User.all 这一行只给你users 表的记录,如果你也想要records 表的行,那么你必须按照下面。

现在下面的行是给你users 表的结果以及来自records 表的所有相关记录

User.includes(:records)

您不会看到来自users 表的重复记录。 因为它将查询 2 个表,一个在 users 上,另一个在 records

希望您通过这篇文章得到更多的澄清。

【讨论】:

  • 感谢您的解释,现在已经很清楚了。
【解决方案2】:

正如 Pavan 所说,我更改了 users = User.joins(:records) for users = User.allUser.includes(:records) 并且工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多