我一直在模特中阻止对某些模型的更新:
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默认值,还是已被覆盖以防止更新。还有另一种方法可以阻止记录更新,同时允许我覆盖特定字段(并且仅在我的插件应用于此模型的实例中)。
答案 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