ActiveRecord Optimistic Locking
参考: http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
Rails(っていうかActiveRecord)での楽観的ロックを使う場合のドキュメント見ながらやってみた
とりあえず実検証でのアプリケーションを作る必要があるので(ry
app/controllers/entries_controller.rb
class EntriesController < ApplicationController
def show
@entries = Entry.all
end
def edit
@entry= Entry.find(params[:id])
end
def update
entry = Entry.find(params[:entry][:id])
update_params = params.require(:entry).permit(:name)
entry.update(update_params)
redirect_to :action => :show
end
end
app/views/entries/show.erb
<% @entries.each do |sample| %>
<%= link_to sample.name, { :action => "edit", :id => sample.id } %>
<% end %>
app/views/entries/edit.erb
<%= form_for @entry do |f| %>
<%= f.hidden_field :id %>
<%= f.text_field :name %>
<%= f.submit "update" %>
<% end %>
な感じで作ったとして、/entry/editに複数からアクセスしてアップデート処理を行った場合、一方が処理したのを他でアップデートされてデータが破壊されるっていうオチになる
でそういう風にならないようにデータをロックするなりで一方がアップデートして他が同時にアップデートしようとしたような場合にはエラーが起こるように出来る
Entryモデルのマイグレーションを修正
class CreateEntries < ActiveRecord::Migration
def change
create_table :entries do |t|
t.string :name
t.timestamps
t.integer :lock_version, :default => 0
end
end
end
lock_versionっていう名前のカラムを作っておけばそれを利用して楽観的ロックな機能を利用する事が出来る模様。又、モデルにて
class Entry < ActiveRecord::Base
self.locking_column = "lock_entry"
end
のようにlocking_columnでロックに使用するカラムを指定出来る。だから別にlock_versionじゃなきゃダメっていうわけでもない模様
これやれば良いだけのとちょっとアプリケーション自体を修正する必要もある
app/controllers/entries_controller.rbを修正
class EntriesController < ApplicationController
def show
@entries = Entry.all
end
def edit
@entry= Entry.find(params[:id])
end
def update
entry = Entry.find(params[:entry][:id])
# 修正
update_params = params.require(:entry).permit(:name, :lock_version)
entry.update(update_params)
redirect_to :action => :show
end
end
app/views/entries/edit.erbを修正
<%= form_for @entry do |f| %>
<%= f.hidden_field :id %>
<!-- 追加 -->
<%= f.hidden_field :lock_version %>
<%= f.text_field :name %>
<%= f.submit "update" %>
<% end %>
ってな感じでやると、一方がアップデート処理をした後にもう一方側でアップデート処理等を使用とすると「ActiveRecord::StaleObjectError」というようなエラーになる
っていう感じ。疑問なのがこういうテストをどう書くのかっていう所。分かり次第追記する