除了在一个字段外,我怎么能禁止更新?

时间:2010-11-16 07:08:50

标签: ruby-on-rails ruby activerecord

我一直在模特中阻止对某些模型的更新:

def update
  self.errors.add_to_base( "Cannot update a #{ self.to_s }" )
end

我现在正在编写一个插件,为模型提供一些额外的功能,我需要更新模型中的一个字段。如果我没有使用插件,我会直接在模型中执行此操作...

def update
  if self.changed == ['my_field']
    super
  else
    self.errors.add_to_base( "Cannot update a #{ self.to_s }" )       
  end
end

我无法从我的插件中执行相同操作,因为我不知道更新行为是ActiveRecord默认值,还是已被覆盖以防止更新。还有另一种方法可以阻止记录更新,同时允许我覆盖特定字段(并且仅在我的插件应用于此模型的实例中)。

4 个答案:

答案 0 :(得分:12)

首先,你应该为这种事情使用before_update回调而不是覆盖更新。其次,您可以在模型上存储可更新的属性,然后使用插件更新它们。我刚刚在浏览器中写了这个,所以可能是错的。

  attr_accessor :updatable_attributes
  before_update :prevent_update

  private
  def prevent_update
    return true if self.changed == self.updatable_attributes
    self.errors.add_to_base "Cannot update a #{ self.to_s }"
    false
  end
end

答案 1 :(得分:4)

此处游戏的后期,但对于查看此问题的人,您可以使用attr_readonly允许在创建时写入字段,但不允许更新。

请参阅http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html

我认为自Rails 2.0以来它已经可用了

棘手的部分是,如果您有attr_accessible的任何属性,您还必须列出您的只读属性(或者您在创建时遇到质量分配错误):

class Post < ActiveRecord::Base
  attr_readonly :original_title
  attr_accessible :latest_title, :original_title
end

答案 2 :(得分:0)

这是为了防止大规模分配吗? attr_accessible / attr_protected会不能满足您的需求吗?


编辑,只是为了说明关于回调的一般观点。

 module MyModule
   def MyModule.included(base)
     base.send :alias_method_chain, :prevent_update, :exceptions
   end

   def prevent_update_with_exceptions
   end
 end

 class MyModel < ActiveRecord::Base
   before_validation :prevent_update

   def prevent_update
   end

   include MyModule
 end

答案 3 :(得分:0)

我只是使用rails params.require方法将您想要允许的属性列入白名单。

def update
  if @model.update(update_model_params)
    render json: @model, status: :ok
  else
    render json: @model.errors, status: :unprocessable_entity
  end
end

private
  def update_prediction_params
    params.require(:model).permit(:editable_attribute)
  end