Я использую Rails 6.1.3.2
и пытаюсь сделать сохранение вложенных атрибутов более эффективным. Используемая база данных — MySQL.
BoardSet.rb
class BoardSet < ApplicationRecord
has_many :boards, inverse_of: :board_set, foreign_key: 'board_set_id', dependent: :destroy
accepts_nested_attributes_for :boards
Board.рб
class Board < ApplicationRecord
has_many :cells, inverse_of: :board, foreign_key: 'board_id', dependent: :destroy
accepts_nested_attributes_for :cells
Cell.rb
class Cell < ApplicationRecord
belongs_to :board, inverse_of: :cells, foreign_key: 'board_id'
Существует конечная точка Grape::API, такая:
params do
requires :name, type: String, desc: 'BoardSet name'
optional :boards, as: :boards_attributes, type: Array[JSON] do
# more params
optional :cells, as: :cells_attributes, type: Array[JSON] do
# more params
end
end
end
post do
board_set = BoardSet.new(declared(params, include_missing: false))
board_set.save!
end
Краткое описание основы кода: BoardSet содержит Boards, которые содержат ячейки. Существует конечная точка Grape::API, куда можно передавать данные через PUT
, которые затем сохраняются в базе данных.
Экономить с помощью board_set.save!
очень неэффективно. BoardSet обычно содержит 40
Доски, каждая из которых может содержать 20
Ячейки. Таким образом, всего имеется более 40 * 20 = 800
операторов SQL INSERT
(по одному для каждой ячейки).
Я попробовал эти попытки улучшения:
BoardSet.import [board_set], recursive: true
, но recursive
поддерживается только для PostgeSQL, а не для MySQL, который я использую.board_set
включая доски с пустыми ячейками, затем перенесите ID досок в ячейки и сохраните их массово. Однако мне не удалось удалить ячейки, я пытался использовать cloned_board = board.dup
и cloned_board.cells = []
для сохранения пустых копий, но он все равно сохраняет все ячейки в cloned_board_set.save!
(где cloned_board_set
содержит клонированные доски с пустыми ячейками).accepts_nested_attributes_for :cells
из Board.rb
, чтобы предотвратить автоматическое сохранение всех ячеек board_set.save!
. Однако это приводит к исключению BoardSet.new(declared(params, include_missing: false))
, поскольку параметр cells_attributes
неизвестен.🤔 А знаете ли вы, что...
Ruby on Rails создан на основе языка программирования Ruby и был впервые выпущен в 2005 году.
Вместо того, чтобы сохранять все объекты в одной строке, попробуйте выполнить следующие 3 шага:
После рельсов 6 мы можем сделать вставить все
board_set = BoardSet.new(объявлен(params[:name], include_missing: false))