2016-11-19 49 views
0

一个int数组上执行detect时,它的工作原理:Rails - 如何在执行检测方法时避免使用数据库?

@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时,它会执行查询。这是真的吗?

回答

1

Rails的实际执行SELECT COUNT(*)查询,当你调用@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? 
+0

呀谢谢,我只是种想通了,这可能是延迟抓取,因为我没有使用之前的数据,以检测。但是当我使用它时,这个“额外的查询”消失了,谢谢:) –

0

在你的情况,你应该使用活动记录和SQL请求。在活动记录关系

@current_category = @categories.find_by(id: params[:category]) 

使用数组方法倾向于获取所有数据再申请内存的算法,而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 
相关问题