Как отметил выше, вам нужно сгенерировать SQL с IS
ключевым словом, чтобы определить, является ли столбец NULL
. Вместо того, чтобы препирать это самостоятельно, вы можете передать хэш до where
и позволить ActiveRecord обрабатывать тонкости; i.e:
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
Как в стороне, это будет отличное место для использования области.
Edit для деталей:
(Оговорка:.. SQL является спецификация, а не реализация, а SQL генерируется рельсам зависит от адаптера базы данных Следующие действия могут варьироваться в зависимости от вашего выбора базы данных)
Ok, несколько вещей:
Вы с помощью 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 может определить, следует ли использовать =
или IS NULL
, посмотрев на хэш, который вы передаете на номер where
. Если вы передадите фрагмент, он понятия не имеет, поэтому он применяет его вслепую.
SQL обычно использует ключевое слово 'IS', чтобы определить, имеет ли значение значение null, см. Http://stackoverflow.com/questions/1833949/why-is-null-not-equal-to-null-false. – bdares