在电子商务商店应用程序中,我想检索与通过搜索表单输入的first_name
匹配的所有订单,其中pay == true。搜索表单通过参数Parameters: {"utf8"=>"✓", "search"=>"john", "commit"=>"Search"}
提交搜索词。在控制器中
@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 )
@order
中的查询工作得很好,如果只返回一个user
,例如只有一个用户名为john。但是,如果多个用户名为John,则会返回多个用户ID,并返回错误消息ActiveRecord::StatementInvalid
。我的理解是,一旦`@users.ids是一个具有多个值的数组,查询就会停止工作。
如何构造以下查询:对于每个user_id,返回所有支付等于true的订单(user.orders)。
Models
user.rb
has_many :orders
order.rb
belongs_to :users
答案 0 :(得分:0)
您应该使用带有WHERE IN子句
的嵌套查询,而不是两个查询SELECT * from Order WHERE user_id IN (SELECT user_id FROM users WHERE first_name LIKE ?) AND paid = true
答案 1 :(得分:0)
这应该做:
Order.joins(:user).where(users: { name: params[:search] }, paid: true)
它使用INNER JOIN
生成一个查询:
SELECT "orders".*
FROM "orders"
INNER JOIN "users" ON "users"."id" = "orders"."user_id"
WHERE "users"."name" = 'Test User' AND "orders"."paid" = 't'
答案 2 :(得分:0)
有很多方法可以解决这个问题。
您可以使用Nic Nilov建议使用JOIN,但如果使用范围构建@users
查询并且您不想手动内联这些范围,则可能会很困难。
您也可以使用子查询,因为Rails4中的ActiveRecord足够聪明当您在where
中使用关系时,您需要使用where
的哈希形式:
@users = User.search(params[:search])
# @users should be a User::ActiveRecord_Relation now.
@orders = Order.where(:user_id => @users, :paid => true)
最终将使用SQL:
select *
from orders
where paid = 't'
and user_id in (
select id
from users
where /* whatever `search` does... */
)
这里的优势在于,只要它返回ActiveRecord关系,您就不需要知道User.search
的作用。
如果您的@users
实际上是一个数组(id
个或整个User
个实例),那么您完全按照相同的方式执行此操作:
# Suppose @users is an array of Users or an array of User ids...
@orders = Order.where(:user_id => @users, :paid => true)
和ActiveRecord将在不必做任何额外操作的情况下弄清楚如何处理@users
数组。