【问题标题】:Readonly attributes/keys with MongoMapperMongoMapper 的只读属性/键
【发布时间】:2012-02-07 23:11:48
【问题描述】:

我想知道是否可以将属性键设为只读。这意味着它只能在创建对象时分配

更新:我希望能够使用 update_attributes 之类的东西,并且确保该方法只会更新可以被覆盖的密钥。例如,如果我有

class User 
    include MongoMapper::Document

    key :firstName, String, :required => true
    key :lastName,  String, :required => true
    key :username,  String, :required => true, :unique => true, :readonly => true
    key :password,  String, :required => true

end

(只读验证是伪代码,我希望存在这样的东西)

那么我希望下面的代码会引发错误或失败

user = User.find_by_username("foo")
user.update_attributes({:username => "bar"})
puts "You cannot change the username" unless user.valid?

我也想要这样的东西,但是是另外一回事

user.update_attributes({:unwantedKey => "fail!"})
puts "You cannot add keys that are not in the User scheme" unless user.valid?

【问题讨论】:

  • 作为程序员的你有责任在分配或不分配某些东西时负责。还是您的意思是您想避免通过参数更改密钥?然后你可以使用attr_accessbile :key_x
  • @three 我用一个例子更新了这个问题。
  • @GuidoMB 我很困惑为什么你想要你所要求的行为。对于您要解决的任何问题,这听起来像是错误的解决方案。你能提供更多动力吗?
  • @PlasticChicken 我在用户实体上使用 Sinatra 公开 CRUD 操作。在更新方法中,API 的使用者不能对用户实体进行任何更新,除了用户名字段。这就是我使用 update_attributes 方法的原因,因为我不想手动更新每个更改。但我不想更改用户名字段

标签: ruby mongodb mongomapper


【解决方案1】:

我会重新考虑您的要求,即您需要通过验证来执行此操作,而不是使用自定义控制器过滤或 attr_accessible 来控制 accessibilty

如果验证确实是正确的解决方案,像three suggests 这样滚动你自己的解决方案是个好主意,这里有一些用于检查数据库的身份映射安全代码:

validate :username_unchanged, :only_existing_keys, :on => :update

def db_version
  # drop to the driver to get around the identity map
  # (identity map is off by default)
  collection.find_one(:_id => self.id)
end

def username_unchanged
  unless username == db_version['username']
    errors.add(:username, 'cannot be changed')
  end
end

def only_existing_keys
  extra_keys = to_mongo.keys - db_version.keys
  unless extra_keys.size == 0
    errors.add(:base, 'You cannot add keys to the schema')
  end
end

但要小心! MongoMapper 不存储值为nil的键。这将破坏上面的only_existing_keys 方法,因此您可能必须在某处存储一组有效键。

希望这是一个足够的起点。

【讨论】:

    【解决方案2】:

    您可以像这样引入自定义验证:

    before_update :check_username
    validate :read_only
    
    def check_username
      @temp_username = self.username
    end
    
    def read_only
      false if self.username != self.temp_username
    end
    

    不确定这是否可行,但您有回调和验证,您可以使用两者来确保没有任何更改。

    http://mongomapper.com/documentation/plugins/callbacks.html http://mongomapper.com/documentation/plugins/validations.html

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 2014-08-22
      • 2015-02-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多