【问题标题】:How to set read-only on a rails model using a attribute within the model?如何使用模型中的属性在 Rails 模型上设置只读?
【发布时间】:2019-04-28 00:55:03
【问题描述】:

如果同一模型中的属性设置为 true,我如何将模型设置为每次访问时只读?

我到处看了看,只读模型似乎只有很少的文档甚至网络结果。

编辑(附加信息): 我的模型(application.rb)中有两种方法 - 不是私有的

  def lock()
    self.locked = true
    save(validate: false)
  end

  def unlock()
    self.locked = false
    save(validate: false)
  end

我在更新时从我​​的应用程序控制器调用它们:

if params[:application][:locked] == false
  @application.unlock
  return
elsif params[:application][:locked] == true
  @application.lock
  return
end

在模型 (application.rb) 中我有 - 不是私下的:

  def readonly?
    locked == true
  end

【问题讨论】:

  • @iGian - 这有点重复。我这样做是因为我觉得这个话题与我在那篇文章的主要问题有点偏离主题,所以我想确保它们分开存在,以便分别回答这两个问题(并希望帮助其他人解决这些问题)。这是关于根据模型中的属性使模型只读,另一个是关于只允许特定属性为只读。
  • @notADevAccount 当您说“在 Rails 模型上只读”时,您是否打算将整个模型(所有记录)设置为只读?还是仅为该模型的一个实例设置只读(每个实例动态解析)?
  • @Jay-ArPolidario - 是的,我需要按实例设置它,因为每条记录都有一个名为“锁定”的属性,该属性应该确定该特定记录是否为只读。如果为 true,则它是只读的,并且不应允许任何写入。
  • @notADevAccount 我明白了,那么我想我的答案就是你要找的吗? :)

标签: ruby-on-rails model readonly readonly-attribute


【解决方案1】:

更新:

# app/models/application.rb

# I highly suggest renaming `Application` into something else because, Rails
# already has a same defined constant name `Application` which is defined in your
# app/config/application.rb

class Application < ApplicationRecord
  def lock!
    # depending on your use-case I'll do an `update` below instead
    # self.lock = true
    update!(locked: true)
  end

  def unlock!
    # self.lock = false
    update!(locked: false)
  end
end

# app/models/user.rb
class User < ApplicationRecord
  belongs_to :application

  def readonly?
    # this is still subject to race-condition even though already `reloaded`
    application.reload.locked || some_user_attribute == 'HELLO WORLD!'
  end
end

# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :application

  def readonly?
    # this is still subject to race-condition even though already `reloaded`
    application.reload.locked || some_comment_attribute_like_is_disabled?
  end
end

请注意,我在那里添加了一个 belongs_to 关联,因为您很可能需要它,因为您所说的 Application 实际上已经是一个正常模型。如果您没有此关联,并且在内部将 locked 设置为您的 Application 类的类实例变量(即您有 @locked 类实例变量),那么(取决于您的要求),您将存在以下问题:1)持久性,因为每个请求(每个不同的进程/服务器)将默认为locked = nil(这可能对您来说是个问题,也可能不是问题),以及 2)并发性,因为线程共享此类实例变量的值,这意味着同时请求将需要独立评估此 @locked 值;如果@locked 在一个线程中设置为true,而在另一个线程中@locked 被覆盖并设置为false,这将变得有潜在危险。但如果这些都不是问题,我仍然可以更新我的答案以不使用belongs_to :application;告诉我。

【讨论】:

  • 所以我仍然很难理解这意味着什么。是否在用户中设置只读然后使其检查应用程序是否为每个实例只读?我的应用模型是:class Application &lt; ApplicationRecord
  • @notADevAccount 哦,我明白当您说application.rb 时,我以为您指的是“常规命名”app/config/application.rb 类。不管你设置什么类self.locked = true or false,为了确保线程安全,你仍然需要Thread.current之类的东西。
  • @notADevAccount 不过,要回答您的问题,是的,def readonly?instance 方法,因为 class 方法将类似于 def self.readonly?。因为它是一个instance 方法,所以是的,该方法是按模型的实例评估的(这与 Rails 如何正确实现此def readonly 方法的预期一致),并且我验证了该方法在实例时被调用/调用该模型已创建/更新/销毁。
  • @notADevAccount 我现在正在更新我的代码以反映我假设的不正确的“application.rb”代码
  • @notADevAccount 哦我现在明白了,Application 实际上是一个普通模型,而不是ApplicationRecord 的抽象子类?并且它有一个名为locked 的属性?那么是的,我认为您不必担心这里的线程安全性。我更新了我的答案。
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
相关资源
最近更新 更多