首页 > 解决方案 > 在一个 POST 请求中创建多个 ActiveRecord 对象时的最佳做法是什么

问题描述

在我们的 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数组并保存每个条目的片段,然后在迭代所有班次后显示错误,我认为它会按预期工作。但是这个解决方案并不让我感到骄傲,也不觉得它像红宝石一样。

标签: ruby-on-rails

解决方案


您可以在数据库事务中包装多条记录的创建。这将更快,并确保所有记录要么一起创建要么不创建,例如:

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

推荐阅读