2012-09-24 10 views
6

codice rilevante: http://pastebin.com/EnLJUJ8GRails 3: Devo salvare esplicitamente un oggetto in un callback after_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 

Sto facendo un piccolo compito app. Ogni attività è assegnata a una stanza. Una volta aggiunta un'attività, desidero utilizzare una richiamata per verificare se ci sono attività nella stessa stanza prima e dopo l'attività che ho appena aggiunto (sebbene il mio codice gestisca solo un caso limite in questo momento).

Quindi ho deciso di utilizzare after_create (poiché l'utente controllerà manualmente questo se lo modificano, quindi non after_save), quindi potrei usare due ambiti e un metodo di classe per interrogare le attività nel giorno, nella stanza, e ordinali per tempo. Quindi trovo l'oggetto nell'array e inizio usando le istruzioni if.

Devo salvare l'oggetto in modo esplicito. Funziona. Ma mi sembra strano che lo stia facendo. Non ho molta esperienza (prima app), quindi non sono sicuro se questo è disapprovato o se è convenzionale. Ho cercato un gruppo e ho esaminato un libro di consultazione, ma non ho visto nulla di specifico.

Grazie.

risposta

3

Questo mi sembra un compito per before_create per me. Se devi salvare nel tuo callback after_*, probabilmente hai intenzione di usare una callback before_*.

In before_create non è necessario chiamare save, poiché il salvataggio si verifica dopo l'esecuzione del codice di richiamata.

E invece di salvare successivamente le query per vedere se si ottengono 2 o più ritorni di oggetti, si dovrebbe interrogare per un oggetto che si scontrerà prima di salvare.

Nel codice pseudo, quello che hai ora:

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 

ciò che si dovrebbe avere:

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 

Qualcosa di più simile a questo:

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

Dal momento che gli ambiti non sarebbero caricare questo oggetto (o mi sbaglio di questo?), avrei bisogno di inserire questo oggetto nell'array @tasks manualmente, corretto? – douglas

+0

Vedere la mia modifica. In pratica, verifica la presenza di 1 conflitto prima di salvare, piuttosto che vedere se la query restituisce 2 o più oggetti dopo il salvataggio. –

+0

Controllare per un record nel database il metodo finder ActiveRecord 'esiste?' Deve essere usato. Vedi [Active API API Dock] (http://apidock.com/rails/ActiveRecord/FinderMethods/exists%3F) – unnu

Problemi correlati