我的activerecord搜索出现问题。我以为我的模型设置正确,但是我的连接很差(不确定连接或联合是否是正确的方法?不应该这么困难)。
我有导游为有start_dates的旅行创建出价。我想创建一个已过期的出价列表(即开始日期是过去的)。如果出价被拒绝,参与者也可以拥有LosingBids
在一个完美的世界中,我会有一个结果集,其中包括失败的出价和该指南的过期出价,但我发现有两个不同的结果集。不幸的是,我无法获得任何“过期的出价”。代码注释中的结果/错误。
class GuidesController < ApplicationController
def expired_declined
#this declined_bids call works
@declined_bids = LosingBid.where("guide_id = ?", current_guide.id.to_s)
#this expired_bids call returns Trips, not Bids
@expired_bids = Bid.where("guide_id = ?", current_guide.id.to_s).expired
#this expired_bids call gives me the following error:
#SQLite3::SQLException: no such column: trips.start_date: SELECT 1 AS one FROM #”bids" WHERE (guide_id = '1') AND (trips.start_date < '2018-05-30') LIMIT ?
@expired_bids = Bid.where("guide_id = ?", current_guide.id.to_s).where("trips.start_date < ?", Date.today)
end
end
class Guide < ApplicationRecord
has_many :bids
has_many :losing_bids
end
class Trip < ApplicationRecord
has_many :bids
end
class Bid < ApplicationRecord
belongs_to :trip
belongs_to :guide
def self.expired
Trip.where("start_date <= ?", Date.today) #.where("guide_id = ?", current_guide.id.to_s)
end
end
class LosingBid < ApplicationRecord
belongs_to :trip
belongs_to :guide
end
答案 0 :(得分:0)
Trip.where("start_date <= ?", Date.today).bids
会将过期的出价退回给您。
您应该在旅行中移动expired
范围,而不是出价。
如果您想在Bid上使用范围,则可以定义。
class Bid
scope :expired, -> { joins(:trip).where('trips.start_date <= ?', Date.current) }
end
答案 1 :(得分:0)
我真的会怀疑你是否需要一个单独的LosingBid
模型,或者只是创建重复和不必要的复杂性。而只需将enum column添加到包含状态的出价:
class Bid
enum status: [:pending, :declined, :expired, :accepted]
end
这只是一个简单的整数列,用作位掩码。
这将让您通过以下方式查询:
Bid.pending
Bid.expired
Bid.where(status: [:pending, :accepted])
Bid.where.not(status: :accepted)
您可以通过以下方式拒绝出价:
class BidsController
# PATCH /bids/decline
def reject
@bid.declined!
redirect_to bid, notice: 'Bid declined'
end
end
然后,您可以设置每天运行一次的计划任务,以自动使任务过期(例如使用whenever gem):
every 1.days do
runner "BidExpiryService.perform"
end
# app/services/bid_expiry_service.rb
module BidExpiryService
def self.perform
bids = Bid.pending
.joins(:trip)
.where('trips.start_date <= ?', Date.current)
bids.update_all(status: Bid.statuses[:expired])
# @todo notify guides that bid has expired
end
end