Rails 3:我应该在after_create回调中显式保存对象吗?

dou*_*las 7 ruby ruby-on-rails callback

相关代码:http://pastebin.com/EnLJUJ8G

class Task < ActiveRecord::Base
  after_create :check_room_schedule

  ...

  scope :for_date, lambda { |date| where(day: date) }
  scope :for_room, lambda { |room| where(room: room) }

  scope :room_stats, lambda { |room| where(room: room) }
  scope :gear_stats, lambda { |gear| where(gear: gear) } 

  def check_room_schedule
    @tasks = Task.for_date(self.day).for_room(self.room).list_in_asc_order
    @self_position = @tasks.index(self)

    if @tasks.length <= 2
      if @self_position == 0 
        self.notes = "There is another meeting in 
    this room beginning at # {@tasks[1].begin.strftime("%I:%M%P")}."
        self.save
      end
    end
  end

  private

    def self.list_in_asc_order
      order('begin asc')
    end
end
Run Code Online (Sandbox Code Playgroud)

我正在制作一个小任务应用程序.每个任务都分配给一个房间.一旦我添加了一个任务,我想使用一个回调来检查在我刚刚添加的任务之前和之后是否在同一个房间里有任务(尽管我的代码现在只处理一个边缘情况).

所以我决定使用after_create(因为如果他们编辑它,用户将手动检查它,因此不是after_save)所以我可以使用两个范围和一个类方法来查询当天,在房间中的任务,并按顺序排序时间.然后我在数组中找到对象并开始使用if语句.

我必须明确保存对象.有用.但我这样做感觉很奇怪.我不是太有经验(第一个应用程序),所以我不确定这是否是不满意或是否是惯例.我搜索了一堆并浏览了一本参考书,但我没有看到任何具体的内容.

谢谢.

Ale*_*yne 3

这对我来说似乎是一项任务before_create。如果您必须在after_*回调中保存,您可能打算使用before_*回调。

您不必before_create调用save,因为保存是在回调代码为您运行之后发生的。

您不应该保存然后查询以查看是否获得 2 个或更多对象返回,而应该在保存之前查询一个会发生冲突的对象。

在伪代码中,您现在拥有的内容是:

after creation
  now that I'm saved, find all tasks in my room and at my time
  did I find more than one?
    Am I the first one?
      yes: add note about another task, then save again
      no: everything is fine, no need to re-save any edits
Run Code Online (Sandbox Code Playgroud)

你应该拥有什么:

before creation
  is there at least 1 task in this room at the same time?
    yes: add note about another task
    no: everything is fine, allow saving without modification
Run Code Online (Sandbox Code Playgroud)

更像这样的东西:

before_create :check_room_schedule
def check_room_schedule
  conflicting_task = Task.for_date(self.day)
                         .for_room(self.room)
                         .where(begin: self.begin) # unsure what logic you need here...
                         .first
  if conflicting_task
    self.notes =
      "There is another meeting in this room beginning at #{conflicting_task.begin.strftime("%I:%M%P")}."
  end
end
Run Code Online (Sandbox Code Playgroud)