Проверьте последний сохраненный элемент, который игнорирует Object.new - PullRequest
0 голосов
/ 26 мая 2018

У меня есть стандартное представление Rails, которое отображает окно предупреждения о состоянии даты на странице new.html.erb.

<% if @user.items.last.issue_date + 2.years > Date.today %>
  ...show warning...
<% end %>

Это будет подавлять, потому что последняя запись ассоциируется с пользователем созданным пустым объектомв контроллере для формы

def new
  @user = User.find(params[:user_id])
  @item = @user.items.new
end

Похоже, что я могу обойти это, выполнив

<% if @user.items.offset(0).last.issue_date + 2.years > Date.today %>

, но это, похоже, не должно работать вообще, потому что документы Postgres говорят

OFFSET 0 - это то же самое, что и пропуск предложения OFFSET.

Итак, у меня есть 2 вопроса:

  • Есть ли лучший способпроверить только те записи, которые были сохранены в базе данных?
  • Почему поведение вызова смещения ActiveRecord (по-видимому) отличается от того, что в документации Postgres должно быть?

1 Ответ

0 голосов
/ 26 мая 2018

Новый @item, созданный вами в контроллере, находится в вашей коллекции @user.items, но еще не сохранен в базе данных.

Именно поэтому добавление .offset(0) работает для вас,потому что, подобно предложению .where(), вы изменяете условия возвращаемых записей только на те, которые возвращены из базы данных, из которых ваша новая запись не является одной из.

Альтернативаспособ отфильтровать это может выглядеть следующим образом:

@user.items.reject(&:new_record?).last

Или это:

@user.items.reject { |item| item == @item }.last

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

В противном случае то, что у вас есть, работает, но я бы использовал менее хрупкий (смещения могут измениться) и более откровенный запрос, например:

@user.items.
  where('issue_date < ?', 2.years.ago).
  order(issue_date: :desc).
  limit(1).
  last

И в идеале вы можетеоберните это в User метод запроса или область действия в модели с именем что-то вроде @user.issues.expired или @user.issued_less_than(2.years.ago), или что-то еще, что работает для вашего приложения.

Кроме того, я надеюсь, что @user.items заказан наотношения, потому что Postgres не всеспособы возврата товаров в любом конкретном порядке, если вы не укажете один.

has_many :items, -> { order(id: :desc) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...