Ich habe ein Modell Produkt und es gehört zu einer Kategorie (category_id in products table). Ich möchte eine Abfrage schreiben, die die ersten 20 Produkte mit ihrem Kategorienamen aufnimmt. Ich habe 2 Möglichkeiten, es zu holen:Welche ist bevorzugt,: enthält oder: verbindet?
Verwenden
includes
, wie folgt aus:Product.includes(:category). order(:updated_at). limit(20)
und in den Ansichten wie diese den Kategorienamen nehmen:
<%= product.category.name if product.category %>
Dies wird Abfrage erstellen wie folgt:
SELECT `products`.* from `products` ORDER BY `products`.updated_at LIMIT 20 SELECT `categories`.* from `categories` WHERE `categories`.id IN (1,2,3,4,5..,25)
Verwenden
joins
wie folgt aus:Product.joins("LEFT JOIN categories ON categories.id = products.category_id"). select("products.*, categories.name as category_name"). order(:updated_at). limit(20)
und es in Ansichten wie diese verwenden:
SELECT products.*, categories.name as category_name from `products` LEFT JOIN categories ON categories.id = products.category_id ORDER BY `products`.updated_at LIMIT 20
Methode 1 hat die:
<%= product.category_name %>
Dies wird Abfrage wie folgt erzeugen Vorteil, dass wir Model-Level-Methoden verwenden können, die auf dem Category-Modell geschrieben wurden, und der Code ist m Erz pflegbar. Aber es hat den Nachteil, dass es eine separate Abfrage verwendet, um die Kategorien zu finden, die die IN-Klausel verwenden.
Welcher ist der bevorzugte Weg?
Es gibt auch Methode 3: Product.Eager_load (: Kategorien) –
@FrederickCheung ..Ich kann keine Dokumentation zu dieser Methode finden .. was macht es? – rubyprince
Derselbe Effekt wie includes (Sie erhalten vollständige Instanzen der Fledge-Kategorie bereit), aber mit einer Joins-basierten Abfrage. –