ruby on rails—当模型有许多子模型时,设置最后更新模型的用户的更好方法



我有一个模型,我将其称为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问题

最新更新