Что является лучшим методом при создании множества объектов ActiveRecord в одном запросе POST - PullRequest
0 голосов
/ 09 июля 2019

В нашем приложении rails 5.2.3 и ruby ​​2.6.0 мы разрабатываем систему бронирования, где пользователи могут публиковать время и даты, когда они доступны.Одна из запрашиваемых функций заключается в том, что пользователи могут указывать период дат, другими словами, дату начала и окончания.Мой вопрос заключается в том, как лучше всего создавать объекты ActiveRecord для всех этих дат.В настоящее время у меня есть эта часть всего решения, так как я решил получить некоторую информацию / отзывы, прежде чем продолжить.

#ShiftController 

def create
  start = DateTime.parse(shift_params)
  stop = DateTime.parse(shift_params)

  days_between = (start.to_date..stop.to_date).count
  shifts_to_save = []

  days_between.times do |i|
    stop_time = stop - days_between + i
    shift = Shift.new(food: params[:shift][:food], start_time: start, end_time: stop_time)
    shifts_to_save.push shift
    current_user.shifts << shift
  end
end

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

1 Ответ

2 голосов
/ 09 июля 2019

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

Shift.transaction do
  # create shifts inside here using save! or create! to ensure rollback upon failure
end

Однако вставка вышеуказанной логики в транзакцию выглядит как большой кусок процедурного кода. Вероятно, было бы лучше Rails-y определить вовлеченные концепции предметной области и перенести их на уровень модели для облегчения понимания и автономного модульного тестирования, например:

#ShiftController 

def create
  start = DateTime.parse(shift_params)
  stop = DateTime.parse(shift_params)

  Shift.indicate_availability(
    user: current_user,
    start: start,
    stop: stop,
    food: params[:food]
  )
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...