2012-09-24 6 views
6

関連するコード:http://pastebin.com/EnLJUJ8GRails 3:a​​fter_createコールバックにオブジェクトを明示的に保存する必要がありますか?

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 

私は小さなタスクのアプリを作ってるんです。各タスクは部屋に割り当てられます。タスクを追加したら、コールバックを使用して、前に追加したタスクの前後に同じ部屋にタスクがあるかどうかを確認したいと思います。

私はafter_createを使用することに決めました(ユーザーが手動でこれをチェックするので、after_saveはチェックされません)ので、2つのスコープとクラスメソッドを使用して、時間通りに注文してください。私は配列内のオブジェクトを見つけ、if文を使い始める。

オブジェクトを明示的に保存する必要があります。できます。しかし、私はそれをやっていることが変だと感じています。私はあまりにも経験豊富ではない(最初のアプリ)ので、これが怒っているのか、それが慣習であるのか分かりません。私は束を探して参考書を見てきましたが、私はこの特定のものは見ていません。

ありがとうございました。

答えて

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 

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 

このようなより多くの何か:

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 
+0

スコープがロードされませんので、このオブジェクト(または私はこれについて間違っていますか?)、このオブジェクトを手動で@tasks配列に挿入する必要があります。 – douglas

+0

私の編集を参照してください。保存後にクエリが2つ以上のオブジェクトを返すかどうかを見るのではなく、保存する前に基本的に1つの競合をチェックします。 –

+0

データベース内のレコードをチェックすると、ActiveRecordファインダメソッド 'exists? 'を使用する必要があります。 [Active Record API Dock](http://apidock.com/rails/ActiveRecord/FinderMethods/exists%3F) – unnu