0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】lock_versionの役割とネストフォームでの使用例

Posted at

はじめに

Railsが提供する楽観的ロックの仕組みであるlock_versionについて、ネストしたフォームでの使用例を学習した記録です。

lock_versionとは

Railsのモデルにlock_versionという整数カラムを追加すると、自動的に楽観的ロックが有効になります。

  • 複数ユーザーが同時に編集することを許容しつつ、保存時に衝突を検知する仕組み
  • Active Recordはレコードが更新されるたびにlock_versionの値を1ずつ増やす
  • 保存時に送信されたlock_versionとDBの値を比較し、不一致ならActiveRecord::StaleObjectErrorを発生させる

ネストしたフォームでの使用例

モデル定義

# app/models/project.rb
class Project < ApplicationRecord
  has_many :tasks, dependent: :destroy
  accepts_nested_attributes_for :tasks
end

# app/models/task.rb
class Task < ApplicationRecord
  belongs_to :project
end

マイグレーション

  • 両方のテーブルにlock_versionカラムを追加する
add_column :projects, :lock_version, :integer, default: 0, null: false
add_column :tasks, :lock_version, :integer, default: 0, null: false

ビュー(フォーム)

  • 各モデルにlock_versionhidden_fieldで埋め込む
<%= form_with(model: @project) do |f| %>
  <%= f.text_field :name %>
  <%= f.hidden_field :lock_version %>

  <%= f.fields_for :tasks do |task_form| %>
    <%= task_form.text_field :title %>
    <%= task_form.hidden_field :lock_version %>
  <% end %>

  <%= f.submit %>
<% end %>

コントローラ

  • ストロングパラメータでlock_versionを許可する
def project_params
  params.require(:project).permit(
    :name, :lock_version,
    tasks_attributes: [:id, :title, :lock_version, :_destroy]
  )
end

動作イメージ

親モデル(Project)でも子モデル(Task)でも、基本的な流れは同じです。

  1. ユーザーAとユーザーBが同じレコードを編集開始(両者のフォームのlock_versionは 0)
  2. ユーザーAが先に保存 → DB のlock_versionが1に更新される
  3. ユーザーBが保存しようとすると、送信されたlock_version=0とDBの1が不一致
    ActiveRecord::StaleObjectErrorが発生

ポイント

  • 親と子のlock_versionは独立して管理される
  • 親が更新できても子で衝突することがあるため、親子を常に一貫性のある状態で保存したい場合は、トランザクションでまとめるのが安全

おわりに

フォーム内にhidden_fieldlock_versionを含めるだけで衝突を検知できるのはシンプルで便利です。ただし、親と子のlock_versionは独立しているため、親子を常に一貫性のある状態で保存したい場合はトランザクションを使う必要があります。またStaleObjectErrorrescueしてユーザーに再編集を促す仕組みを入れると、実運用でより安心です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?