2009-04-07 6 views
7

Beim Schreiben der "create" -Methode für ein Objekt in einer Ruby on Rails-App habe ich zwei Methoden verwendet. Ich würde gerne eine Methode für einen saubereren und konsistenteren Code verwenden. Ich werde die beiden folgenden Methoden auflisten. Weiß jemand, ob einer besser ist als der andere? Wenn ja warum?Wenn Sie ein Objekt in Ruby on Rails erstellen, welche Methode bevorzugen Sie und warum?

Methode 1:

def create1 
    # is this unsecure? should we grab user_id from the session 
    params[:venue]['user_id'] = params[:user_id] 

    begin 
    venue = Venue.create(params[:venue]) 
    @user_venues = @user.venues 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    rescue ActiveRecord::RecordInvalid 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 

Methode 2:

def create2 
    # is this unsecure? should we grab user_id from the session 
    params[:venue]['user_id'] = params[:user_id] 

    venue = Venue.new(params[:venue]) 
    if venue.save 
    @user_venues = @user.venues 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    else 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 
+0

Ich denke, du meinst "create!" nicht "create" in Methode 1. "create" löst keine Ausnahme aus; Bei Validierungsfehlern wird einfach false zurückgegeben. –

+0

Sie sind richtig, danke, dass Sie darauf hingewiesen haben – Tony

Antwort

4
class VenuesController < ApplicationController 
    def create 
    @venue = @user.venues.create!(params[:venue]) 
    render :partial => 'venue_select_box', :success => true, :status => :ok 
    end 

    rescue_from ActiveRecord::RecordInvalid do 
    render :text => 'Put errors in here', :success => false, :status => :unprocessable_entity 
    end 
end 

Mit @user.venues auf diese Weise sicherzustellen, dass die Benutzer-ID wird immer entsprechend eingestellt werden. Außerdem schützt ActiveRecord das Feld :user_id vor der Zuweisung im Verlauf des Aufrufs #create!. Daher können Angriffe von außen nicht :user_id ändern.

In Ihren Tests können Sie überprüfen, ob das Ausführen eines POST für: create eine ActiveRecord :: RecordInvalid-Ausnahme auslöst.

+0

Chaos Punkt, dass "Ausnahmen sollten nicht für Routine-Bedingungen verwendet werden" ist ein guter. Rails hat sich jedoch anders entschieden: "rescue_from ActiveRecord :: RecordInvalid" ist gängige Praxis. –

3

ich von der Schule des Denkens bin, dass Ausnahmen sollten nicht für Routinebedingungen verwendet werden, so würde ich die zweite sagen ist besser.

2

Es kommt darauf an. Wenn Sie erwarten, dass alle create-Anweisungen funktionieren, verwenden Sie erstere, da der Fehler beim Erstellen und Speichern außergewöhnlich ist und möglicherweise eine Bedingung ist, von der das Programm nicht ohne weiteres wiederhergestellt werden kann. Wenn Sie die relationale Integrität (Fremdschlüssel-Migrationen durch RedHill Consulting) verwenden, werden außerdem Ausnahmebedingungen für Fremdschlüsselverletzungen ausgelöst, sodass Sie sie wahrscheinlich beim Erstellen oder Aktualisieren abfangen möchten.

Die zweite ist praktikabel und gut, wenn die Abfrage nicht erfolgreich ist, was Sie als Teil der täglichen Operation dieser bestimmten Aktion erwarten.

Auch Ihr Code Kommentar über Sitzung ist unsicher - die Sitzung ist der Ort, um die user_id zu setzen. Solange Sie überprüfen, ob der Benutzer authentifiziert wurde, bevor Sie etwas anderes tun, werden Sie in Ordnung sein.

+0

Da dies eine create-Aktion ist, sagst du, dass Version 1 gut ist, wenn ich clientseitige Validierung habe, aber Version 2 ist besser, wenn ich serverseitige Validierung verwende? – Tony

+0

Nicht ganz ... mit ein paar Ausnahmen wollen Sie * immer * auf der Serverseite validieren, als Vorsichtsmaßnahme (die clientseitige Validierung kann immer von einem böswilligen Angreifer deaktiviert werden) ... (Aufteilung in zwei Kommentare) –

+0

Meine Faustregel, verwende ich save(), wenn ich erwarte, dass die Operation abgeschlossen wird, ohne in eine DB-Einschränkung zu kommen, und create(), wenn ich erwarte, dass es ... hilft das? Ich implementiere auch immer einen globalen Ausnahmebehandler, um Streufehler zu erfassen. –

1

Ich stimme Don Kommentar völlig zu. Aber ich würde mit dem Teil user_id noch einen Schritt weiter gehen und ihn als Vorfilter für das Modell festlegen.

Verwandte Themen