0

In einer E-Commerce-Shop-Anwendung möchte ich alle Bestellungen abrufen, die eine first_name entsprechen, die über ein Suchformular eingegeben wurde und wo bezahlt == wahr ist. Das Suchformular reicht den Suchbegriff über die Parameter Parameters: {"utf8"=>"✓", "search"=>"john", "commit"=>"Search"} ein. In der SteuerungRails/SQL: Verwenden eines Arrays als Suchparameter

@users = User.search(params[:search]) #returns all users with the matching first_name, e.g. 'john' 
@order = Order.where('user_id = ? AND paid = ?', @users.ids, true) 

Die Abfrage in @order funktioniert gut, wenn nur ein user zurückgegeben wird, zum Beispiel nur ein Benutzer heißt John. Wenn jedoch mehrere Benutzer John heißen, werden mehrere Benutzer-IDs zurückgegeben und die Fehlernachricht ActiveRecord::StatementInvalid wird zurückgegeben. Mein Verständnis ist, dass die Abfrage nicht mehr funktioniert, wenn `@users.ids ein Array mit mehr als einem Wert ist.

Wie strukturiere ich die folgende Abfrage: Geben Sie für jede user_id alle Bestellungen (user.orders) zurück, bei denen bezahlt gleich wahr ist.

Models 
user.rb 
has_many :orders 

order.rb 
belongs_to :users 

Antwort

0

Es gibt verschiedene Möglichkeiten, dies zu tun.

Sie können ein JOIN als Nic Nilov schlägt vor, aber das kann schwierig sein, wenn Ihre @users Abfrage mit Bereichen erstellt wird und Sie diese Bereiche nicht manuell inline einbinden möchten.

Sie auch eine Unterabfrage, da Active in Rails4 verwenden könnte, ist intelligent genug, um das Richtige tun, wenn Sie eine Beziehung in einem where verwenden, müssen Sie nur noch den Hash-Form where verwenden:

@users = User.search(params[:search]) 
# @users should be a User::ActiveRecord_Relation now. 
@orders = Order.where(:user_id => @users, :paid => true) 

Dieser Wille am Ende mit SQL wie:

select * 
from orders 
where paid = 't' 
    and user_id in (
    select id 
    from users 
    where /* whatever `search` does... */ 
) 

Der hier Vorteil ist, dass Sie müssen lange nicht wissen, was User.search tut so, wie es eine Active Beziehung zurückkehrt.

Wenn Ihr @users ist tatsächlich ein Array (von id s oder ganze User Instanzen) dann würden Sie es tun genau die gleiche Weise:

# Suppose @users is an array of Users or an array of User ids... 
@orders = Order.where(:user_id => @users, :paid => true) 

und Active wird herauszufinden, was mit Ihrem @users Array zu tun ohne dass du etwas extra tun musst.

0

Statt zwei Abfragen, sollten Sie eine verschachtelte Abfrage mit einer WHERE IN Klausel verwenden

SELECT * from Order WHERE user_id IN (SELECT user_id FROM users WHERE first_name LIKE ?) AND paid = true 
0

Dies tun sollten:

Order.joins(:user).where(users: { name: params[:search] }, paid: true) 

Es erzeugt eine einzelne Abfrage mit einem INNER JOIN:

SELECT "orders".* 
    FROM "orders" 
    INNER JOIN "users" ON "users"."id" = "orders"."user_id" 
    WHERE "users"."name" = 'Test User' AND "orders"."paid" = 't' 
+0

Das Problem hier ist, dass Sie davon ausgehen, dass 'User.search (s)' ist wirklich 'User.where (: name => s)' anstatt etwa LIKE-Abfrage. –

Verwandte Themen