我有一个我想写的功能,无法弄清楚它是如何工作的。第一行按照它们应该的顺序返回我的步骤,第二行我想返回课程所有步骤中的最后一个匹配步骤。我想我很接近,但需要知道我做错了什么。
course_steps_in_order = course.steps.sort_by(&:component_and_step_order)
last_completed_step = current_user.completed_steps.where("steps.id in ?", course_steps_in_order).last
我收到了错误...
ActiveRecord::StatementInvalid: PG::Error: ERROR: syntax error at or near "1"
LINE 1: ... WHERE "user_steps"."user_id" = 3 AND (step.id in 1,2,4,8,5,...
^
: SELECT "steps".* FROM "steps" INNER JOIN "user_steps" ON "steps"."id" = "user_steps"."step_id" WHERE "user_steps"."user_id" = 3 AND (step.id in 1,2,4,8,5,3,7,6,9) ORDER BY "steps"."id" DESC LIMIT 1
根据以下模型,课程有很多组成部分,步骤很多......
class Course < ActiveRecord::Base
has_many :components, :dependent => :destroy, :order => "component_order"
has_many :steps, :through => :components, :dependent => :destroy
end
class Component < ActiveRecord::Base
belongs_to :course
has_many :steps, :dependent => :destroy, :order => "step_order"
end
class Step < ActiveRecord::Base
belongs_to :component
def component_and_step_order
component_order * 100 + step_order
end
end
答案 0 :(得分:3)
你有两个问题:一个你知道,一个你不知道。第一个也是最明显的问题是clyfe为您解决的SQL语法错误。第二个问题是IN
不保证任何特定的顺序,所以:
current_user.completed_steps.where("steps.id in (?)", course_steps_in_order).last
不保证会为您提供id
位于course_steps_in_order
的最后一步,甚至不保证从一次执行到下一次执行会产生相同的结果。如果要按特定顺序从SQL中获取结果,必须使用ORDER BY子句显式指定该顺序。例如,我刚刚在我的一个PostgreSQL表中执行了此操作:
=> select id from some_table where id in (1,2,3,4,5);
id
----
1
5
2
3
4
当您期望4
时,您的方法会将5
作为最后一个。
请允许我重复一遍:关系数据库是基于设置而且本质上是无序的,如果您需要按特定顺序执行任何操作,那么必须明确指定ORDER BY子句中的顺序。
如果您希望last
来电显示有用的内容,则需要将component_and_step_order
方法转换为.order
来电,并将其包含在current_user.completed_steps.where
查询中。< / p>
答案 1 :(得分:2)
添加包含括号的括号:
...
last_completed_step = current_user.completed_steps.where("steps.id in (?)", course_steps_in_order).last
现在查询将正确生成:
... AND (step.id in (1,2,4,8,5))