Identify Resource that Does Not Have a Payment Association with SQL query

断了今生、忘了曾经 提交于 2019-12-25 08:35:18

问题


I have an index page where I want to both show featured and standard boards. A featured board has has_one payment, a standard board does not.

class Payment < ApplicationRecord
  belongs_to :board
end

class Board < ApplicationRecord
  has_one :payment
end

So I can identify a featured board by joining the payments and therefor removing the standard boards.

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

Now I want to get the standard listings by doing:

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

But this both returns the featured and the standard boards.

I'm looking for a way to get standard listings (boards that do not have a payment) and I just can't figure out how to do that.


回答1:


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

I would highly suggest you read this great blog post visualizing all different joins. It also explains your use case: You first left join the boards with the payments and then filter out all board who do have a payment.




回答2:


The more compositional way of handling this is:

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

You're encouraged to use scopes to your advantage. For example:

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;



回答3:


Create a new column in your Board model.

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

Then change the create method of your Payment Controller to include this method from the Board model.

Board.rb

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

If you post the code that you use to create a payment I can help you more but it should be trivial.

Then you can create a scope

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

You will then be able to use Board.payment_made to return Boards where the payment Boolean attribute is true.



来源:https://stackoverflow.com/questions/42455547/identify-resource-that-does-not-have-a-payment-association-with-sql-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!