ActiveRecord查找许多日期与许多其他日期(Rails)不重叠的位置

时间:2016-03-14 09:40:00

标签: sql ruby-on-rails postgresql activerecord

我想做的事情非常复杂,但请耐心等待。我正在使用Rails,ActiveRecord,Postgres。

活动有很多位置,有很多开始和结束时间。用户可以将自己分配给活动。

用户一次只能在一个地方。因此,在“将自己分配到活动页面”时,我只需要显示与用户已经分配的事件没有重叠时间的事件。

我知道你可以通过加入来做到这一点,但我无法弄清楚如何。

型号:

class Event < ActiveRecord::Base
  has_many :locations
  has_many :event_times
  has_many :assignments
end

class Location < ActiveRecord::Base
  belongs_to :event
  has_many :event_times
end

class EventTime < ActiveRecord::Base
  belongs_to :location
  belongs_to :event
end

class User < ActiveRecord::Base
  has_many :assignments
end

class Assignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :event
end

总结了我正在努力做的事情。我知道这太糟糕了。

user_events = Assignment.where(user_id: current_user.id).pluck(:event_id)
blocked_event_times = EventTime.where(event_id: user_events)

blocked_query_string = ""

blocked_event_times.each do |bt|
  blocked_query_string += "NOT( event_times.start <= '#{bt.end}'::timestamp AND event_times.end >= '#{bt.start}'::timestamp ) AND "
end
blocked_query_string += "1=1"


return Event.includes(:event_times).where(blocked_query_string).references(:event_times)

我是否在正确的轨道上认为我应该做一些像(伪代码)的事情:

@acceptable_times = EventTime.all LEFT JOIN user's_assigned_event_times

然后获取事件,其中所有事件的时间都出现在@acceptable_times

1 个答案:

答案 0 :(得分:0)

我不完全确定数据格式或EventTime模型是如何工作的,所以这是另一种基于Assignment start_timeend_time以及start_time的事件的解决方案{1}}和end_time

我猜你可以通过下面的例子传递EventTime而不是Event的实例。

def overlaps_existing_commitment?(event)
  current_user.assignments.where("assignments.start_time < ? AND assignments.end_time > ?, event.start_time, event.end_time).any?
end

所以认为你可以循环事件:

events_to_render = []

@events.each do |event|
  unless overlaps_existing_commitment?(event)
    events_to_render << event
  end
end

然后,您可以在视图中使用events_to_render数组。

我相信有很多更好的方法,但希望能提供一些灵感来找到你满意的解决方案!

其他几件事:

  • 我看得越多,我就越相信不需要EventTime模型。通过向其他模型添加start_timeend_time属性,它将使您的生活更轻松。

  • 利用'?'在您的SQL查询中。