如何根据控制器操作 [:create, :update] 使模型回调有条件?

How to make a model callback conditional based upon controller actions [:create, :update]?

我想在goal.rb

中做这样的事情
  before_save :set_tag_owner,:if => [:create, :update]

  def set_tag_owner
    # Set the owner of some tags based on the current tag_list
    set_owner_tag_list_on(self.user, :tags, self.tag_list)
    self.tag_list = nil
  end

我希望此方法在仅保存 goals_controller.

的创建和更新操作之前起作用

否则我 运行 会遇到标记问题,当目标被标记为已完成时,标记就会消失,因为 set_tag_owner 将其标记设置为 nil

  def mark_accomplished
    @goal.update(accomplished: true)
  end

  def create
    @goal = current_user.goals.build(goal_params)
    @goal.save
    respond_modal_with @goal, location: root_path, notice: 'Goal was successfully created! Go chase those dreams!'
  end

  def update
    @goal.update(goal_params)
    respond_modal_with @goal, location: root_path
  end

虽然我需要这一行 self.tag_list = nil 因为没有它标签会被双重渲染

我还尝试通过 before_action 回调在控制器中应用该目标模型逻辑,但即使我将 self 更改为 [=18=,我仍收到 undefined 错误].

另一种方法是添加一个 attr_accessor 到您的模型并使用它来停止 before_save

一个例子

class Goal < ActiveRecord::Base

  attr_accessor :dont_set_tag_owner

  before_save :set_tag_owner, :unless => dont_set_tag_owner

  def set_tag_owner
    # Set the owner of some tags based on the current tag_list
    set_owner_tag_list_on(self.user, :tags, self.tag_list)
    self.tag_list = nil
  end

end

然后,在控制器中

def mark_accomplished
  @goal.update(accomplished: true, :dont_set_tag_owner => true)
end

而且,只是为了给你多一个选择——根据你对updated_at的需要,你也可以这样做

def mark_accomplished
  @goal.update_column(accomplished: true)
end