首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在查询中使用属性或关联属性

在查询中使用属性或关联属性
EN

Stack Overflow用户
提问于 2019-03-05 19:28:14
回答 2查看 184关注 0票数 0

我有一个关于ExtendedEvent的Rails,我用它来封装与具有开始时间和结束时间的事件相关的逻辑,我的应用程序中有几个。它目前看起来是这样的:

类中的用法通常如下所示:

代码语言:javascript
运行
复制
class InAndOutEvent < ApplicationRecord

  include ExtendedEvent

  def configure_extended_event
    @ee_start_date_time = enter_date_time
    @ee_end_date_time = exit_date_time
  end
end

其中enter_date_timeexit_date_time是模型属性。但是,另一种用法如下所示:

代码语言:javascript
运行
复制
class InAndOutEvent < ApplicationRecord
  belongs_to: entry
  belongs_to: exit

  include ExtendedEvent

  def configure_extended_event
    @ee_start_date_time = entry.date_time
    @ee_end_date_time = exit.date_time
  end
end

哦,也有可能我的entryexit关联实际上属于同一个类,这意味着在查询中使用别名:

代码语言:javascript
运行
复制
  belongs_to :entry, class_name: "ThingWithDateTime"
  belongs_to :exit, class_name: "ThingWithDateTime"

我想定义一个类级别的作用域或查找器方法,它允许我根据模型是否与给定的时间范围start_time..end_time重叠来查找包含ExtendedEvent的模型。在明显损坏的伪代码中:

代码语言:javascript
运行
复制
require 'active_support/concern'
module ExtendedEvent
  extend ActiveSupport::Concern

  class_methods do
    def overlaps_with(time_range)
      where(ee_start_date_time: time_range)
        .or(self.where(ee_end_date_time: time_range))
    end
  end

  # ... instance methods as above omitted

end

我知道不可能使用这样的泛型方法,但我的开始/结束时间是由模型属性设置的,所以我觉得这应该是可能的。如果我的属性总是在模型上,我可以用alias_attribute替换定义实例变量,并使用它,如下所示:

代码语言:javascript
运行
复制
alias_attribute :ee_start_time, :enter_date_time

但我认为这不适用于关联上的属性。

有什么方法可以做到这一点吗?我在Ruby2.4上使用的是Rails 5.1。

EN

回答 2

Stack Overflow用户

发布于 2019-03-05 21:45:00

只有在从数据库中搜索字段时,才能使用where,因此,在这种情况下,您必须使用普通拼音(这将很慢):

代码语言:javascript
运行
复制
def self.overlaps_with(time_range)
  select do |instance|
    time_range.include?(instance.ee_start_date_time)
    || time_range.include?(instance.ee_end_date_time)
  end
end

同样,如果你需要一个数组而不是数组(这样你以后就可以在数组上使用像where这样的方法),你可以这样做:

代码语言:javascript
运行
复制
def self.overlaps_with(time_range)
  ids = select do |instance|
    time_range.include?(instance.ee_start_date_time)
    || time_range.include?(instance.ee_end_date_time)
  end.map(&:id)

  where(id: ids)
end
票数 0
EN

Stack Overflow用户

发布于 2019-03-05 22:32:38

您粘贴的模型看起来与查询数据库无关,因此我将使用我自己的示例:

代码语言:javascript
运行
复制
time_range = [1.hour.ago, 1.hour.since]

overlap_records = Model.where('? > models.end_time OR models.start_time < ?', *time_range)

associated_overlap_recs = Assoc.joins(:model).where('? > models.end_time OR models.start_time < ?', *time_range)

确保这两个时间列是复合索引的。

因此,假设有:

代码语言:javascript
运行
复制
class InAndOutEvent < ActiveRecord::Base
  belongs_to :entry, class_name: "ThingWithDateTime"
  belongs_to :exit, class_name: "ThingWithDateTime"
end

class ThingWithDateTime < ActiveRecord::Base
end

您应该能够这样做:

代码语言:javascript
运行
复制
# data "from the association"
entry_time = thing_with_date_time_foo.date_time
exit_time = thing_with_date_time_bar.date_time

# to adhere to your api that accepts a `time_range` parameter
time_range = [entry_time, exit_time]
InAndOutEvent.joins(:entry, :exit).where(
  '? > thing_with_date_times.date_time OR thing_with_date_times_in_and_out_events.start_time < ?',
  *time_range
)

具体的查询取决于ActiveRecord为连接“选择”的table aliases

如果其中一个或两个关联是多态的,情况就会变得相当复杂。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55001776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档