【问题标题】:How do I lock records in Rails 3 for a specific amount of time?如何将 Rails 3 中的记录锁定特定时间?
【发布时间】:2011-10-13 03:09:32
【问题描述】:

我想要做的基本上是让用户获得对记录的锁定并将其保留一段时间,以便他们可以对其进行更改,例如维基百科。因此,假设一篇维基百科文章给用户一个小时的时间来编辑它,然后其他用户可以编辑它。

如何使用 Rails 3 实现这一目标?我已经阅读并发现悲观锁定是我应该使用的锁。鉴于此......我会在一个小时后使用什么样的机制来释放锁?

我的堆栈是 Rails 3、Heroku、PostgreSQL。

感谢您的任何回答,如果可以的话,我很乐意看到代码,那将是非常棒的!

【问题讨论】:

    标签: ruby-on-rails-3 rails-postgresql pessimistic-locking


    【解决方案1】:

    这是一个创建锁但不删除它们的示例。

    这个由你来决定。

    在本例中,锁会在一小时后过期,但要完成应用,它们应该在成功更新帖子时自动删除。

    working example

    或阅读

    relevant commit

    【讨论】:

      【解决方案2】:

      您可以使用acts_as_lockable_by gem 来做到这一点。

      假设您有一个只能由一个用户编辑的患者 (ActiveRecord) 类,并且它应该被锁定到该用户直到他决定释放它:

      class Patient < ApplicationRecord
        acts_as_lockable_by :id, ttl: 30.seconds
      end
      

      然后您可以在控制器中执行此操作:

      class PatientsController < ApplicationController
        def edit
          if patient.lock(current_user.id) 
            # It will be locked for 30 seconds for the current user
            # You will need to renew the lock by calling /patients/:id/renew_lock
          else
            # Could not lock the patient record which means it is already locked by another user
          end
        end
      
        def renew_lock
          if patient.renew_lock(current_user.id)
            # lock renewed return 200
          else
            # could not renew the lock, it might be already released
          end
        end
      
        private
      
        def patient
          @patient ||= Patient.find(params[:id])
        end
      end
      

      【讨论】:

        【解决方案3】:

        添加一个名为 "editable_until":datetime 的字段,并在创建记录时设置特定日期(Time.now + 30.min f.e.)。并简单地查询该字段以了解用户是否有权更新记录。

        class Post << AR
          before_validation :set_editable_time
        
          validate :is_editable
        
          def editable?
            self.editable_until.nil? || self.editable_until >= Time.now
          end
        
        protected
          def is_editable
            self.errors[:editable_until] << "cannot be edited anymore" unless editable?
          end
        
          def set_editable_time
            self.editable_until ||= Time.now + 30.min
          end
        end
        
        Post.create(:params....)
        => <Post, ID:1, :editable_until => "2011-10-13 15:00:00">
        
        Post.first.editable?
        => true
        
        sleep 1.hour
        
        Post.first.editable?
        => false
        

        【讨论】:

        • 更正了我的帖子,有一个错误的运算符(&&,但应该是..nil?||)。欢迎你:)
        • 关于这个的另一个问题...这是否意味着我实际上根本不需要悲观锁定来解决这个问题?
        • 不,您无需再做任何事情。您可以做的一件事是将我的方法更改为验证回调......会更好......明白我的意思吗?
        • Timecop 用于测试而不是 sleep: github.com/travisjeffery/timecop
        猜你喜欢
        • 1970-01-01
        • 2021-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 1970-01-01
        • 2022-12-23
        • 1970-01-01
        相关资源
        最近更新 更多