识别没有与SQL查询的支付关联的资源

时间:2017-02-25 11:36:51

标签: ruby-on-rails join activerecord

我有一个索引页面,我想要显示特色和标准板。特色董事会已经付款,标准董事会没有。

class Payment < ApplicationRecord
  belongs_to :board
end

class Board < ApplicationRecord
  has_one :payment
end

因此,我可以通过加入付款来识别特色板,从而删除标准板。

Board.joins(:payment).where(category: category, confirmed: true)

现在,我希望通过以下方式获取标准列表:

Board.where(category: category, confirmed: true)

但这两者都会返回特色和标准板。

我正在寻找获得标准列表的方法(没有付款的主板),我只是无法弄清楚如何做到这一点。

3 个答案:

答案 0 :(得分:1)

Board
  .joins("LEFT JOIN payments ON boards.id = payments.board_id")
  .where(payments: {id: nil})

我强烈建议你read this great blog post visualizing all different joins。它还解释了您的使用案例:您首先离开加入董事会的付款,然后过滤掉所有确实付款的董事会。

答案 1 :(得分:0)

处理这个问题的更多组合方式是:

Board.references(:payment).where.not(payment: { id: nil })

我们鼓励您使用范围对您有利。例如:

class Board
  scope :with_payments, -> { includes(:payment) }
  scope :featured, -> { with_payments.where.not(payment: { id: nil }) }
end

Board.featured # => SELECT * FROM boards JOIN payments ON payments.board_id = board.id AND payments.id IS NOT NULL;

答案 2 :(得分:-1)

在Board模型中创建一个新列。

class AddPaymentToBoards < ActiveRecord::Migration
  def change
    add_column :boards, :payment, :boolean, default: false
  end
end

然后更改支付控制器的创建方法,以便从Board模型中包含此方法。

Board.rb

def payment_made
  self.update_attribute(:payment, true)
end 

如果您发布用于创建付款的代码,我可以为您提供更多帮助,但这应该是微不足道的。

然后你可以创建一个范围

scope :payment_made, -> { where payment: true }

然后,您就可以使用Board.payment_made返回付款布尔属性为true的单位。