У розробці веб-додатків на основі Rails часто виникає потреба оновлювати кілька записів одночасно з однієї форми. Це може стати проблемою, якщо ви не знаєте правильного підходу. У цій статті ми розглянемо ефективний спосіб реалізації масового оновлення записів у Rails.
Однією з найпоширеніших ситуацій, коли вам потрібно оновити кілька записів одночасно, є сценарій редагування даних у формі, де кожен запис представляє окремий об’єкт моделі. Наприклад, ви маєте таблицю статистики команди з ігрових матчів, і вам потрібно дозволити тренерам вносити зміни у статистику кількох гравців одночасно.
Перш ніж розглядати сам процес масового оновлення, давайте спочатку зрозуміємо, як виглядає форма, яку ми будемо використовувати для збору даних. У нашому прикладі ми використовуємо Rails 7.0.4 і форму на основі функціоналу form_with
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<%= form_with url: stats_update_path(params[:id], params[:team_id]) do |form| %> <table class="min-w-full text-left text-sm"> <tr class=""> <td>#</td> <td>Name</td> <td>FGM</td> <td>FGA</td> </tr> <% @roster.each_with_index do |player, index| %> <% player_stats = Stat.where("schedule_id = ? and team_id = ? and player_sport_id = ?", @schedule.id, params[:team_id], player.id).first %> <%= fields_for "stats[]" do |stats| %> <tr class=""> <td><%= player.number %></td> <td><%= player.player.name %></td> <td><%= stats.text_field :fgm, id: "fgm#{index}", value: player_stats.fgm %></td> <td><%= stats.text_field :fga, id: "fga#{index}", value: player_stats.fga %></td> <%= stats.hidden_field :id, id: "id#{index}", value: player_stats.id %> <%= stats.hidden_field :team_id, id: "team_id#{index}", value: params[:team_id] %> <%= stats.hidden_field :schedule_id, id: "schedule_id#{index}", value: @schedule.id %> <%= stats.hidden_field :player_sport_id, id: "player_sport_id#{index}", value: player.id %> </tr> <% end %> <% end %> </table> <% end %> |
Ця форма дозволяє тренерам вводити статистику для кожного гравця команди. Ключовим елементом є використання fields_for
для генерації поля для кожного гравця, яке буде зберігати статистику. Кожен рядок таблиці представляє окремого гравця з полями для введення FGM (промахи по метанню) та FGA (всього метань).
Тепер, коли ми маємо форму для вводу даних, перейдемо до обробки цих даних в контролері. У нашому випадку ми маємо методи edit
, update
і create
.
def edit
@schedule = Schedule.find(params[:id])
@roster = PlayerSport.includes(:player).where("team_id = ? and active = ?", params[:team_id], 1)
@stats = Stat.where("team_id = ? and schedule_id = ?", params[:team_id], params[:schedule_id])
end
def update
respond_to do |format|
if Stat.update(id: stats_params)
format.html { redirect_to schedule_url(game.sport_id), notice: "Stat was successfully updated." }
format.json { render :show, status: :ok, location: @stat }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @stat.errors, status: :unprocessable_entity }
end
end
end
def create
if stats_params.present?
respond_to do |format|
if Stat.create(stats_params)
format.html { redirect_to stat_url(game.sport_id), notice: "Stat was successfully created." }
format.json { render :show, status: :created, location: @stat }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json