Right now I am getting the dealings by dealings.all and do the below reject statement , but is there a way that I can just query this in just one go ? I have a few ruby codes like pluck and max and I am just wondering if I can mix ruby code in sql code.

dealings.reject {|n|

(n.item_rank == :import && n.dealings.pluck(:status).max == Contract::import) || (n.item_rank == :process && n.dealings.pluck(:status).max == Contract::process) || (n.item_rank == :export && n.dealings.pluck(:status).max == Contract::export) }

end

1 Answers

0
neversleep On Best Solutions

I believe this is possible using sub-query. Here is a raw sql example:

negotiations = Negotiation.from('(select negotiations.*, (select max(status) from deal_buildings where deal_buildings.deal_id = negotiations.id) max_status from negotiations) negotiations')
negotiations = negotiations.where(business_rank: [17, 19, 22])
negotiations = negotiations.where(main_member_id: 7)
negotiations = negotiations.where(
  '((business_rank = ? and max_status = ?) or (business_rank = ? and max_status = ?) or (business_rank = ? and max_status = ?)) is false',
  'application', Supplier::Building::STATUS_APPLY,
  'agreement', Supplier::Building::STATUS_CONTRACT,
  'settlement', Supplier::Building::STATUS_SETTLEMENT
)

And query object:

class NegotiationsQuery
  def all
    Negotiation.from(negotiations_and_max_status_query)
  end

  private

  def negotiations
    @negotiations ||= Arel::Table.new(:negotiations)
  end

  def deal_buildings
    @deal_buildings ||= Arel::Table.new(:deal_buildings)
  end

  def max_status_query
    deal_buildings.project(deal_buildings[:status].maximum).where(
      deal_buildings[:deal_id].eq(negotiations[:id])
    ).as('max_status')
  end

  def negotiations_and_max_status_query
    negotiations.project(negotiations[Arel.star], max_status_query).as('negotiations')
  end
end
  negotiations = NegotiationsQuery.new.all
  negotiations = negotiations.where(business_rank: [17, 19, 22])
  negotiations = negotiations.where(main_member_id: 7)
  negotiations = negotiations.where(
    '((business_rank = ? and max_status = ?) or (business_rank = ? and max_status = ?) or (business_rank = ? and max_status = ?)) is false',
    'application', Supplier::Building::STATUS_APPLY,
    'agreement', Supplier::Building::STATUS_CONTRACT,
    'settlement', Supplier::Building::STATUS_SETTLEMENT
  )