2016-11-19 48 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 
相關問題