【问题标题】:scope for count children has_many relationcount children has_many 关系的范围
【发布时间】:2013-04-25 02:42:00
【问题描述】:

我有两个模型

# == Schema Information
#
# Table name: answers
#
#  id          :integer          not null, primary key
#  content     :text
#  question_id :integer
#  accept      :boolean
#  created_at  :datetime         not null
#  updated_at  :datetime         not null    
#  user_id     :integer
#

class Answer < ActiveRecord::Base
  attr_accessible :accept, :content, :question_id, :user
  belongs_to :question
  belongs_to :user
  delegate :username, to: :user, allow_nil: true, prefix: 'owner'
end

和问题

# == Schema Information
#
# Table name: questions
#
#  id           :integer          not null, primary key
#  title        :string(255)
#  content      :text             default(""), not null
#  created_at   :datetime         not null
#  updated_at   :datetime         not null
#  user_id      :integer
#  viewed_count :integer          default(0)
#

class Question < ActiveRecord::Base

  validates_presence_of :title, :content, :user
  attr_accessible :content, :title, :tag_list
  acts_as_taggable
  belongs_to :user, :counter_cache => true
  has_many :answers
  delegate :username, to: :user, allow_nil: true, prefix: 'owner'
  scope :owner, joins(:user)
  scope :without_answer, joins(:answers).
     select('questions.id').
     group('questions.id').
     having('count(answers.id) = 0')

  validate :validation_of_tag_list

  def self.no_answer
    Question.all.select{|question|question.answers.count == 0}
  end

作用域without_answer和类方法no_answer理论上应该是一样的。但是,我在控制台中运行它们如下:

Loading development environment (Rails 3.2.13)
irb(main):001:0> Question.without_answer
  Question Load (0.6ms)  SELECT questions.id FROM `questions` INNER JOIN `answers` ON `answers`.`question_id` = `questions`.`id` GROUP BY questions.id HAVING count(answers.id) = 0
=> []
irb(main):002:0> Question.no_answer
  Question Load (0.6ms)  SELECT `questions`.* FROM `questions` 
   (0.5ms)  SELECT COUNT(*) FROM `answers` WHERE `answers`.`question_id` = 1
   (0.4ms)  SELECT COUNT(*) FROM `answers` WHERE `answers`.`question_id` = 2
   (0.4ms)  SELECT COUNT(*) FROM `answers` WHERE `answers`.`question_id` = 16
   (0.4ms)  SELECT COUNT(*) FROM `answers` WHERE `answers`.`question_id` = 17
   (0.3ms)  SELECT COUNT(*) FROM `answers` WHERE `answers`.`question_id` = 34
=> [#<Question id: 2, title: "Here is the second", content: "here you go\r\n", created_at: "2013-04-20 00:34:15", updated_at: "2013-04-20 00:34:15", user_id: nil, viewed_count: 0>, #<Question id: 16, title: "my question", content: "Here is my question", created_at: "2013-04-21 02:02:47", updated_at: "2013-04-23 02:29:27", user_id: 1, viewed_count: 1>, #<Question id: 17, title: "Hello", content: "me", created_at: "2013-04-23 00:37:56", updated_at: "2013-04-23 00:37:56", user_id: nil, viewed_count: 0>, #<Question id: 34, title: "Question title", content: "question content", created_at: "2013-04-23 04:57:49", updated_at: "2013-04-23 04:57:49", user_id: 42, viewed_count: 0>]
  1. 为什么示波器不能按预期工作?
  2. 在这种情况下,哪种方式会更好,甚至更好的解决方案?

【问题讨论】:

    标签: sql ruby-on-rails-3 scope


    【解决方案1】:

    您的without_answer 范围非常接近,但需要像这样的外部连接:

    scope :without_answer,
       joins('LEFT OUTER JOIN answers ON answers.question_id = questions.id').
       select('questions.id').
       group('questions.id').
       having('count(answers.id) = 0')
    

    然后,您可以通过length 获取计数:

    Question.without_answer.length
    

    注意:如果您希望 without_answerno_answer 相同(即返回实际的 Question 对象),则需要删除 select

    计算未回答问题的一种更简单、更快捷的方法如下:

    Question.joins('LEFT OUTER JOIN answers ON answers.question_id = questions.id').
             where('answers.id' => nil).count
    

    此外,这将返回与 no_answer 相同的内容,只需使用 all 而不是 count

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 1970-01-01
      • 2017-11-11
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 2012-04-28
      • 2011-05-23
      • 1970-01-01
      相关资源
      最近更新 更多