我有一个模型,我将其称为Parent。当此模型更新时,我注册哪个用户在父模型上执行了此最后更新。我在ParentsController中这样做:
def update
@parent = Parent.find(params[:id])
@parent.assign_attributes(params[:parent])
@parent.last_editor = current_user
if @parent.save
# continue....
这个效果很好。控制器告诉模型谁是当前用户。这两个关注点分离得很好。
但是父模型有许多不同的子模型,我想更新父的last_editor当它的子更新时。( last_editor 是用户)。
我可以这样做:
class ChildOnesController
# ...
def create
@child_one = ChildOne.new(params[:child_one])
if @child_one.save
@child_one.parent.update_attribute(last_editor: current_user)
else
# ...
end
end
def update
@child_one = ChildOne.find(params[:id])
if @child_one.update_attributes(params[:child_one])
@child_one.parent.update_attribute(last_editor: current_user)
# continue....
end
end
def destroy
# Destroy...then
@child_one.parent.update_attribute(last_editor: current_user)
# ...
end
主要问题是:由于我的父模型具有各种子模型,我必须将这些行添加到每个子模型控制器中。是否有更好、更简洁的方法来做到这一点?
非常感谢任何提示!!
你可以使用mixin,并在所有控制器中一致地命名你分配给子节点的实例变量。
module ChildControllerMixin
def update_last_editor
@child.parent.update_attribute(last_editor: current_user) if @child.valid?
end
end
class ChildOnesController
include ChildControllerMixin
after_filter :update_last_editor, only: [:create, :update, :destroy]
end
我不知道这是一个多么好的选择,因为它看起来有点脆弱,但它可能会帮助你。
编辑:你可能要重新考虑为什么你有一个单独的控制器为每个孩子。它们是否足够相似以至于只需要一个控制器?
使用这种方法,您的数据很快就会混乱。您将被迫在控制器中管理每个动作,因此last_editor
设置正确。我建议您这样修改:
# user.rb
def self.current_user=(user)
Thread.current[:current_user] = user
end
def self.current_user
Thread.current[:current_user]
end
现在current_user将在您的模型中使用User.current_user
可用。我们只需要在应用程序控制器中设置它。
# application_controller.rb
before_filter :set_current_user
def set_current_user
User.current_user = current_user
end
从现在起,我们可以在model中创建回调,在每次保存时设置last_editor。
# parent.rb
before_save :set_last_editor
...
def set_last_editor
self.last_editor = User.current_user
end
最后一刻为您的孩子模型。你只需要在子模型的每一个更改上重新保存parent。
# every_children_model.rb
after_save :update_parent
...
def update_parent
# ... get parent
parent.save!
end
现在系统中的任何操作,无论您使用哪个控制器,都将处理last_editor问题