在int数组上执行detect
时,它可以工作:
@number = [1,2,3,4,5,6,7].detect{|n| n == 4}
变量@number
变为4。
但是当我做这样的事情时:
@categories = Category.all
@current_category = @categories.detect{|cat| cat.id == params[:category]}
程序输出
Category Load (0.2ms) SELECT "categories".* FROM "categories"
这意味着它正在使用数据库来查找它。
但是,我试图找到的元素已经在集合@categories
中,我只想找到它以将其分配给变量。
当然,另一种解决方案是实现线性搜索算法,但我只想保持代码尽可能干净。
如何避免使用数据库进行此搜索?
编辑:我刚刚意识到这可能是懒惰的提取。因为在detect
之前,我从不使用@categories
,所以当我执行detect
时它会执行查询。这可能是真的吗?
答案 0 :(得分:1)
当您调用SELECT COUNT(*)
时,Rails实际上正在执行@categories.all
查询,实质上是执行延迟抓取。
您的@categories
对象仍需要在数据库中查询数据。
请参阅此处的文档:http://apidock.com/rails/ActiveRecord/Scoping/Named/ClassMethods/all
posts = Post.all
posts.size # Fires "select count(*) from posts" and returns the count
posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
fruits = Fruit.all
fruits = fruits.where(color: 'red') if options[:red_only]
fruits = fruits.limit(10) if limited?
答案 1 :(得分:0)
在您的情况下,您应该使用活动记录和SQL请求。
@current_category = @categories.find_by(id: params[:category])
在Active Record关系上使用数组方法倾向于获取所有数据然后将算法应用于内存中,而SQL过滤更快。
在你的情况下,我喜欢在我的模型上定义运算符[]
:
#in category.rb
def self.[](x)
self.find_by(id: x)
end
# anywhere after:
if c = Category[params[:id]]
puts "Category found and it's #{c.name} !"
else
puts "Not found :("
end