Комплекс Rails находит на основе ассоциаций, а иногда id равен нулю

71
7

У меня есть приложение rails, и я хочу, чтобы он генерировал отчет

У меня есть модели журнала, клиента, пользователя и проекта.

Журнал может принадлежать проекту и клиенту и всегда принадлежит пользователю.

Когда я создаю отчет. Я могу, например, выбрать пользователя и получить все журналы этого пользователя. Когда я выбираю пользователя и проект, я хочу получить журнал, связанный с пользователем и проектом.

Это была моя первоначальная попытка:

Log.where(user_id: params[:user_id],project _id: params[:project_id],customer_id: params[:customer_id]

Проблема в том, что если я хочу журналы для конкретного проекта или клиента, параметры [: user_id] равны нулю, и это приводит к ошибкам

Итак,

class Log < ActiveRecord::Base
def self.user_try(user)
if user
where(user_id: user)
else
where("end_time IS NOT NULL")
end
end
#corresponding methods for project and customer
end

У меня должно получиться безобразное if..else утверждение, если пользователь равен нулю, из-за where("end_time IS NOT NULL") ошибки where("end_time IS NOT NULL") всегда верны.

Находка теперь такая

Log.user_try(params[:user_id])
.project_try(params[:project_id])
.customer_try(params[:customer_id])

Это работает, но мне действительно не нравится код.

Третья попытка - это то, где я застрял

Я пытаюсь сделать на методе, который выполняет работу для всех трех методов "user_try", передавая параметры в метод как хеш.

Как я могу это сделать?

спросил(а) 2013-04-26T13:33:00+04:00 6 лет, 7 месяцев назад
2
Решение
59

В контроллере

Log.try_find_logs(user_id: params[:user_id],
project_id: params[:project_id],
customer_id: params[:customer_id])

В модели я сопоставляю хэш. Это дает мне массив массивов. Я вставляю оператор & и получаю журналы, у которых есть правильные идентификаторы, даже если у меня нет некоторых параметров.

class Log < ActiveRecord::Base
def self.try_find_logs(options)
a = options.map do |k,v|
where(k => v)
end
a.inject(:&)
end
end

ответил(а) 2013-04-26T14:33:00+04:00 6 лет, 7 месяцев назад
Еще 1 ответ
45

@logs = Log.all
@logs = @logs.where(:user_id => params[:user_id]) unless params[:user_id]
@logs = @logs.where(:project_id => params[:project_id]) unless params[:project_id]
@logs = @logs.where(:user_id => params[:customer_id]) unless params[:customer_id]

На всякий случай, если вы этого не знаете, в приведенном выше примере будет только один запрос к базе данных.


Я бы предложил вам использовать has_scope gem, что делает возможности фильтрации легко расширяемыми. Вы можете добавить еще много фильтров. А также жемчужина игнорирует параметр, если он равен нулю (ваш прецедент).

class Log < ActiveRecord:Base
scope :user, proc { |u_id| where(:user_id => u_id) }
...
end

class LogsController < ApplicationController
has_scope :user
def index
@logs = apply_scopes(Log)
end
...
end

ответил(а) 2013-04-26T13:47:00+04:00 6 лет, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема