ruby on rails 命名范围实现 [英] ruby on rails named scope implementation

查看:40
本文介绍了ruby on rails 命名范围实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘自《使用 Rails 进行敏捷 Web 开发》一书

From the book Agile Web Development With Rails

class Order < ActiveRecord::Base
   named_scope :last_n_days, lambda { |days| {:conditions =>
      ['updated < ?' , days] } }

   named_scope :checks, :conditions => {:pay_type => :check}
end

声明

orders = Orders.checks.last_n_days(7)

将导致仅对数据库进行一次查询.

will result to only one query to the database.

rails 是如何实现的?我是 Ruby 的新手,我想知道是否有一种特殊的构造允许这种情况发生.

How does rails implement this? I'm new to Ruby and I'm wondering if there's a special construct that allows this to happen.

为了能够像这样链接方法,named_scope 生成的函数必须返回自身或一个可以进一步确定范围的对象.但是 Ruby 怎么知道这是最后一个函数调用并且现在应该查询数据库?

To be able to chain methods like that, the functions generated by named_scope must be returning themselves or an object than can be scoped further. But how does Ruby know that it is the last function call and that it should query the database now?

我问这个是因为上面的语句实际上查询了数据库,而不仅仅是返回一个由链接产生的 SQL 语句.

I ask this because the statement above actually queries the database and not just returns an SQL statement that results from chaining.

推荐答案

named_scope 魔术中有两个技巧(或模式,如果你愿意的话).

There are two tricks (or patterns if you will) employed in the named_scope magic.

代理模式 - 在类或关联上调用命名范围方法总是返回 ActiveRecord::NamedScope::Scope 类的实例,而不是过滤后的 AR 对象.这种模式虽然非常有用,但有时会使事情变得有些模糊,因为代理对象的性质是矛盾的.

Proxy pattern - calling a named scope method on a class or an association always returns an instance of the ActiveRecord::NamedScope::Scope class, not a colleciton of filtered AR objects. This pattern, altough very useful, makes things kind of blurry sometimes, since the proxy objects are ambivalent in their nature.

延迟加载 - 由于延迟加载(在这种情况下意味着 - 只有在必要时才访问数据库)命名范围可以链接到您需要使用由定义的集合时的点范围.每当您请求底层集合时,都会评估所有链接的范围并执行数据库查询.

Lazy loading - thanks to lazy loading (which in this context means - hitting the database only if neccessary) named scopes can be chained up to the point when you need to work with the collection defined by the scopes. Whenever you request the underlying colleciton, all the chained scopes are evaluated and a database query is executed.

最后一点:在 IRB 中使用命名范围(或任何使用某种委托的事物)时,需要记住一件事.每次按 Enter 键时,都会评估您事先编写的内容,并对返回值调用 inspect 方法.在链式命名范围的情况下,虽然整个表达式被评估为一个 Scope 实例,但当 IRB 对其调用 inspect 方法时,范围被评估并触发数据库查询.这是因为 inspect 方法通过委托传播到所有范围对象直到底层集合.

One final note: There's one thing to have in mind when playing with named scopes (or with any thing that uses delegation of some kind) in IRB. Everytime you hit Enter, the thing you wrote beforehand is evaluated and the inspect method is called on the returned value. In the case of chained named scopes, although the whole expression is evaluated to a Scope instance, when the IRB calls the inspect method on it, the scopes are evaluated and the database query is fired. This is caused by the fact that the inspect method is by means of delegation propagated through all the scope objects up to the underlying collection.

这篇关于ruby on rails 命名范围实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆