Запрос условной активной записи с рельсами

По умолчанию:complete_at равен нулю. Если я использую полный метод, то завершенный_кат превращается в Time.now. Я проверил это, и он работал нормально. Несмотря на это, мой запрос не работает в случае входящих / исходящих задач. Что действительно странно, так это то, что запрос отлично работает с выполненными задачами. Так что запрос "где" не работает, но "где.не" работает. Вы можете помочь мне с этим?

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

Вот как я сделал атрибут complete_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

1 ответ

Решение

Как указано выше, вам нужно сгенерировать SQL с IS ключевое слово, чтобы определить, является ли столбец 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 - это спецификация, а не реализация, и SQL, сгенерированный rails, зависит от адаптера базы данных. Следующие параметры могут отличаться в зависимости от выбора базы данных.)

Хорошо, несколько вещей:

  1. Вы используете where("completed_at = ?", 'nil'), который на самом деле ищет записи, где completed_at это строка "nil", Это почти наверняка не то, что вы хотите, и имеет другие непредвиденные последствия.

  2. 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, Если вы передаете фрагмент, он понятия не имеет, поэтому применяет его вслепую.

Другие вопросы по тегам