2015-10-06 50 views
2

在我的Ruby on Rails项目中,我有一个邮件程序,它基本上为给定用户准备系统中发生的事情的每日摘要。在邮件收发控制器中,我根据一些常见模式(在特定日期内,未由该用户创作,未标记等)收集来自各种模型的所有相关记录,并且从模型到模型的细微差异。Dry up Rails Active记录查询条件

这里涉及半数模型(和计数),其中大多数对于某些事情(例如发布日期或者是否由管理员标记项目)具有统一的列名称。因此,进入查询的'where大部分是相同的。条件有细微差别,但至少有2或3个条件完全相同。我很容易假设模型之间可能会有更类似的情况,因为我们刚开始使用该功能,但尚未弄清数据的最终形状。

我基本上链接'where'调用每个模型。它激怒我有6行代码如此接近彼此,跨越到我的代码编辑器的权利,但仍然如此相似。我很害怕这样的想法,即在某个时候,我们将不得不改变其中一种“核心”条件,并一次性用多行代码进行转换。

我想做的事情是将一组进入每个查询的核心条件移入某种Proc或其他类型,然后在每个模型(如示波器)上简单地调用它,然后继续'where '与模型特定的条件链。很像每个型号上的scope

我正在努力的是如何做到这一点,同时保持邮件内的代码。我当然知道,我可以在一个关注点内声明一个复杂的范围,然后将它混合到我的模型中,并开始每个具有该范围的查询。然而,这种方式逻辑将远离邮件程序,进入未知领域的模型问题,并且它将使每个模型变得复杂,目前只需要一个庞大系统中的一个小邮件程序。此外,对于某些查询,查询需要User模型的一组详细信息,而且我不希望每个模型都处理User。

我喜欢作用域的活动记录模式通过lambda表达式定义方式(如scope :pending, -> { where(approved: [nil, false]) }),并一直在寻找一种方式来使用类似的语法模型类(外面,我的邮件方法里面可能有tap或类似的东西),但我还没有找到任何这种方法的好例子。

那么,是否有可能实现?我可以在我的邮件收集方法中收集核心'where''内部的某些变量的电话,并将它们应用于多个模型,但仍然可以继续连接where链?

回答

1

阿雷尔的美丽,背后的ActiveRecord查询生成技术,是这一切都完全可组合的,用普通的红宝石。

我理解你的问题,这是你想要做的吗?

def add_on_something(arel_scope) 
    arel_scope.where("magic = true").where("something = 1") 
end 


add_on_something(User).where("more").order("whatever").limit(10) 

add_on_something(Project.where("whatever")).order("something") 

只是普通的ruby方法会做到这一点,你不需要一个特殊的AR功能。因为AR范围已经可组合。

+0

谢谢,看起来像它。我在寻找一个不必要的复杂问题的答案,当然一个简单的本地方法会有很大的帮助。 – user20532

1

你可以这样做:

@report_a = default_scope(ModelA) 
@report_b = default_scope(ModelB) 

private 
def default_scope(model) 
    model. 
    where(approved: [nil, false]). 
    order(:created_at) 
    # ... 
end