[英]conditional active record query with rails
默認情況下:completed_at為零。 如果我使用complete方法,則completed_at變為Time.now。 我檢查了一下,效果很好。 盡管如此,在傳入/傳出任務的情況下,我的查詢無法正常工作。 真正奇怪的是,查詢與已完成的任務完美配合。 因此,“ where”查詢不起作用,而“ where.not”則無效。 你能幫我這個忙嗎?
def incoming_tasks
@user =current_user
@executed_tasks = @user.executed_tasks.where("completed_at = ?", 'nil').order("created_at DESC")
end
def outgoing_tasks
@user = current_user
@assigned_tasks = @user.assigned_tasks.where("completed_at = ?", 'nil').order("created_at DESC")
end
def completed_tasks
@user = current_user
@assigned_tasks = @user.assigned_tasks.where.not("completed_at = ?", 'nil').order("completed_at DESC")
@executed_tasks = @user.executed_tasks.where.not("completed_at = ?", 'nil').order("completed_at DESC")
end
這是我使completed_at屬性具有日期的方法:
def complete
@task = Task.find(params[:id])
@task.update_attribute(:completed_at, Time.now)
redirect_to completed_tasks_user_tasks_path(current_user)
end
如上所述,您需要使用IS
關鍵字生成SQL以確定列是否為NULL
。 您可以自己將哈希傳遞到where
並讓ActiveRecord處理細微差別,而不必自己弄亂它。 即:
def incoming_tasks
@user =current_user
@executed_tasks = @user.executed_tasks.where(completed_at: nil).order("created_at DESC")
end
def outgoing_tasks
@user = current_user
@assigned_tasks = @user.assigned_tasks.where(completed_at: nil).order("created_at DESC")
end
def completed_tasks
@user = current_user
@assigned_tasks = @user.assigned_tasks.where.not(completed_at: nil).order("completed_at DESC")
@executed_tasks = @user.executed_tasks.where.not(completed_at: nil).order("completed_at DESC")
end
順便說一句,這將是使用示波器的好地方。
編輯詳細信息:
(注意:SQL是一個規范,而不是實現,並且rails生成的SQL取決於數據庫適配器。以下內容可能會因您選擇的數據庫而異。)
好的,幾件事:
您使用的是where("completed_at = ?", 'nil')
,它實際上是在查找completed_at
是字符串 "nil"
。 幾乎可以肯定這不是您想要的,並且會帶來其他意想不到的后果。
當涉及到匹配行時,SQL有一種處理NULL
值的非常特殊的方式。 在WHERE
子句中使用=
運算符時,它將忽略具有NULL
值的行。 您必須使用IS NULL
或IS NOT NULL
運算符之一來推斷NULL
值。
考慮表:
| id | completed_at |
| 1 | 2015-07-11 23:23:19.259576 |
| 2 | NULL |
使用以下查詢:
Rails | SQL | Result
where("completed_at = ?", 'nil') | WHERE (completed_at = 'nil') | nothing, since completed_at isn't even a string
where.not("completed_at = ?", 'nil') | WHERE (NOT (completed_at = 'nil')) | only row 1, since = can't match a NULL value, even when negated
where("completed_at = ?", nil) | WHERE (completed_at = NULL) | nothing, you can't test for NULL with the = operator
where.not("completed_at = ?", nil) | WHERE (NOT (completed_at = NULL)) | nothing, you can't test for not NULL with = either
where(completed_at: nil) | WHERE completed_at IS NULL | row 2 only
where.not(completed_at: nil) | WHERE (completed_at IS NOT NULL) | row 1 only
當然, where(completed_at: nil)
只是where('completed_at IS NULL')
簡寫,反之亦然,但是散列格式更加慣用且獨立於數據庫適配器。
所有這一切的神奇之處在於ActiveRecord可以通過查看傳遞給where
的哈希值來確定它應該使用=
還是IS NULL
。 如果傳遞片段,則毫無頭緒,因此會盲目地應用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.