Rails 查找条件...其中属性不是数据库列
我认为可以肯定地说每个人都喜欢在 Rails 中做这样的事情:
Product.find(:all, :conditions => {:featured => true})
这将返回属性“featured”(这是一个数据库列)为 true 的所有产品。但假设我有一个关于 Product 的方法,如下所示:
def display_ready?
(self.photos.length > 0) && (File.exist?(self.file.path))
end
...并且我想查找该方法返回 true 的所有产品。我可以想到几种混乱的方法来做到这一点,但我认为可以肯定地说我们喜欢 Rails,因为大多数事情并不混乱。
我想说这对我来说是一个很常见的问题......我必须想象一个好的答案会帮助很多人。有什么不乱七八糟的想法吗?
I think it's safe to say everyone loves doing something like this in Rails:
Product.find(:all, :conditions => {:featured => true})
This will return all products where the attribute "featured" (which is a database column) is true. But let's say I have a method on Product like this:
def display_ready?
(self.photos.length > 0) && (File.exist?(self.file.path))
end
...and I want to find all products where that method returns true. I can think of several messy ways of doing it, but I think it's also safe to say we love Rails because most things are not messy.
I'd say it's a pretty common problem for me... I'd have to imagine that a good answer will help many people. Any non-messy ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
过滤这些的唯一可靠的方法是检索所有记录并通过选择运行它们的有点丑陋的方法:
这是极其低效的,特别是如果您有大量可能不合格的产品。
更好的方法是为您的照片设置一个计数器缓存,并在上传文件时设置一个标志:
您需要在“产品”表中添加一列:
这将为您提供一列包含照片数量的列。有一种方法可以在开始时用正确的数字而不是零预先填充这些计数器,但这里没有必要讨论这个问题。
添加一列来记录您的文件标志:
现在保存时触发此操作:
由于这两个属性被呈现到数据库列中,因此您现在可以直接查询它们:
您可以通过编写两个封装该行为的命名范围来清理它。
The only reliable way to filter these is the somewhat ugly method of retrieving all records and running them through a select:
This is inefficient to the extreme especially if you have a large number of products which are probably not going to qualify.
The better way to do this is to have a counter cache for your photos, plus a flag set when your file is uploaded:
You'll need to add a column to the Product table:
This will give you a column with the number of photos. There's a way to pre-populate these counters with the correct numbers at the start instead of zero, but there's no need to get into that here.
Add a column to record your file flag:
Now trigger this when saving:
Since these two attributes are rendered into database columns, you can now query on them directly:
You can clean that up by writing two named scopes that will encapsulate that behavior.
您需要进行两级选择:
1)从数据库中选择所有可能的行。这发生在数据库中。
2) 在 Ruby 中,从所有行中选择有效行。例如
添加:
或者:
第二个select是Array对象的select方法。 select 和 detector 都是一个非常方便的方法。 (Detect 来自 Enumerable,与 Array 混合在一起。)
You need to do a two level select:
1) Select all possible rows from the database. This happens in the db.
2) Within Ruby, select the valid rows from all of the rows. Eg
Added:
Or:
The second select is the select method of the Array object. Select is a very handy method, along with detect. (Detect comes from Enumerable and is mixed in with Array.)