rails-単純なロックを実装して、ユーザーが同じデータを同時に編集できないようにします

StackOverflow https://stackoverflow.com/questions/1803574

質問

別のユーザーが編集している間、ユーザーがデータを編集できないようにする必要があるアプリがあります。私はそれを行うための最良の方法を考えているので、アイデアを求めていました。これまで、キーと値のペアでアプリケーション全体の構成をデータベースに保存する設定モデルを作成しました。したがって、ロックのために、LOCKED_TABLE_UIDと呼ばれる設定インスタンスがあり、テーブルを編集しているユーザーのuser_idまたはテーブルが空いている場合はnull(nil)を保存しました。

>> lock = Setting.find_by_key('LOCKED_TABLE_UID')

次に、ロックを取得および解放するために、アプリケーションコントローラーに2つのメソッドを実装しました。

# current_user returns the user currently logged in
def acquire_lock
  lock = Setting.find_by_key("LOCKED_TABLE_UID")
  if lock.value
    # if lock taken, see if it's the current_user or someone else
    if lock.value.to_i == current_user.id.to_i
      return true
    else
      return false
    end
  else
    # lock is free, assign it to this user
    lock.value = current_user.id
    return true if lock.save
  end
end

def release_lock
  lock = Setting.find_by_key("LOCKED_TABLE_UID")
  if lock.value
    # the lock belongs to current_user, so he can release it
    if lock.value.to_i == current_user.id.to_i
      lock.value = nil
      return true if lock.save
    else
      # not your lock, go away
      return false
    end
  else
    # lock is free, quit bugging
    return true
  end
end

私が望んでいるのは、次のようなロックメカニズムを含む何らかの種類のブロックコードを作成することです。

def some_crud_action
  requires_locking do |lock|
    if lock
      # do some CRUD stuff here
    else
      # decline CRUD and give some error
    end
  end
end

これについて助けていただければ幸いです-しかし、私はそれをすべて達成する方法について他の提案や、私が見落としていたかもしれないことを受け入れています。このロックはアトミックである必要はありませんが、かなり基本的で最も重要です-動作すること:) ありがとう。

役に立ちましたか?

解決

もうすぐです。 require_lockingを作成しますか?あなたが合うと思うアクション。次に、before_filterで処理します。

 before_filter :requires_locking?, :only => [:update, :destroy]
 after_filter :release_lock, :only => [:update, :destroy]

 def requires_locking do |lock|
   unless acquire_lock
      lock = Setting.find_by_key("LOCKED_TABLE_UID")
      user_with_lock = User.find(lock.value)
      flash[:message] = "Action denied: Table locked by: #{user_with_lock.name}"
      redirect_to :back
   end
 end

他のヒント

ActiveRecordの組み込みロック機能を見ましたか?

このアイデアは気に入っていますが、ソリューションに大きな問題があります。テーブル全体のロックを取得および解放しているということです。

大丈夫な非常に小さなアプリの場合、たとえば「PRODUCTS」テーブルにアクセスしようとして数千人のユーザーがいて、誰かが自分の製品とはまったく関係のないエントリを編集しているために待たなければならない場合を想像してください。

よりきめの細かいアプローチを使用して、テーブルではなく特定の行をロックすることもできます。ロックには、テーブル名、行ID、ユーザーIDが含まれます。

acts_as_lockable_by gemは、あなたが求めていることを、より簡単な用語でより少ないコードで正確に実行していると思います。レールやベアルビープロジェクトと簡単に統合できます。

このgemを使用すると、アトミックな lock unlock 、および renew_lock メソッドを取得できます。また、自動期限切れの ttl ロックが発生するため、たわごとがファンに当たり、リソースのロックを解除できなかった場合、自動的にロックが解除されます!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top