【发布时间】:2016-03-14 09:39:59
【问题描述】:
我正在尝试做的事情非常复杂,但请耐心等待。我正在使用 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 中获取所有事件时间都存在的事件
【问题讨论】:
-
不要使用
end作为 ActiveRecord 中的列名。end是 Ruby 中的保留字 - 如果您尝试在没有显式主题的情况下调用它,则会出现语法错误。这是对principle of least suprise 的极大违反。相反,您可能希望遵循时间戳使用的约定:ends_at、starts_at。 -
另外我会考虑将开始和结束时间存储在事件表中以减少复杂程度。
-
问题是,一个事件可以有多个开始和结束时间。感谢您对保留字的提醒。
标签: sql ruby-on-rails postgresql activerecord