问题
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