2013-07-04 9 views
20

Ich bin mit Rails 4.Zugang modellspezifische Konstanten in einer Rails-Ansicht

Ich habe ein Modell Challenge, und in meiner Datenbank Ich bin Speichern der status jeder Herausforderung im Hinblick auf 0-4 genannt.

Aber 0-4 ist nicht sehr semantische so möchte ich ein paar Variablen definieren (Ich bin ein Konstanten angenommen wird), so dass in jedem Controller oder sehe ich durch den Aufruf der Konstante, die die Zahl zugreifen:

# Challenge.rb 
class Challenge < ActiveRecord::Base 
    SUGGESTED = 0 
    APPROVED = 1 
    OPEN = 2 
    VOTING = 3 
    CLOSED = 4 
end 

ich möchte diese meiner Ansicht zuzugreifen:

# challenge/_details.html.erb 
<% if @challenge.status == CLOSED %> 
    Challenge is closed, broheim! 
<% end %> 

Aber meiner Meinung nach will nicht machen.

Was ist der beste Weg, um meine Statusvariablen so einzustellen, dass auf sie überall zugegriffen werden kann, wo ich sie brauche? (Das heißt, an jedem Ort der @challenge Variable vorhanden ist)

+2

empfehle ich Ihnen in diesem Fall einen Hash als eine Konstante zu verwenden. Warum? Weil es die Anzahl der verschiedenen Konstanten Ihres Modells reduziert. Etwas wie: 'STATUSES = {vorgeschlagen: 0, genehmigt: 1, offen: 2, etc: ..}' und Zugriff darauf wie 'Challenge :: STATUSES.approved' – MrYoshiji

Antwort

41

Sie sollten sie wie folgt zugreifen:

Challenge::CLOSED 

Da Ihr CLOSED konstant innerhalb einer Klasse definiert ist, müssen Sie die Konstante Zugriff auf den Bereichsauflösungsoperator verwenden. Also, wenn Ihr Blick möchten Sie es überprüfen:

# challenge/_details.html.erb 
<% if @challenge.status == Challenge::CLOSED %> 
    Challenge is closed, broheim! 
<% end %> 
+1

Das ist ein bisschen überflüssig, wenn man bedenkt, dass meine if-Anweisung bereits referenziert die Variable @challenge Gibt es eine Möglichkeit, das zu tun, das so semantisch ist, dass es sich wie Englisch liest? – alt

+0

Hey danke das ist sehr nützlich für mich. –

9

Es ist eine wirklich schlechte Idee, diese Art von Aussagen zu codieren: Ihr Objekt muss damit umgehen eigene Logik ist. Stellen Sie sich vor, wenn Sie sich irgendwann dazu entscheiden, den Status zu verschmelzen, würden Sie alle Bedingungen in Ihrer Codebasis ändern? Nein, Sie sollten eine Methode verwenden, die die Logik verarbeitet.

Ich würde folgendes tun:

class Challenge < ActiveRecord::Base 
    SUGGESTED = 0 
    APPROVED = 1 
    OPEN = 2 
    VOTING = 3 
    CLOSED = 4 

    #defines: 
    # - suggested? 
    # - approved? 
    # - ... 
    %w(suggested approved open voting closed).each do |state| 
    define_method "#{state}?" do 
     status == self.class.const_get(state.upcase) 
    end 
    end 

    #if you prefer clarity, define each method: 

    def suggested? 
    status == SUGGESTED 
    end 

    #etc... 
end 

Dann Ihrer Ansicht:

<% if @challenge.closed? %> 
+0

Scheint nicht sehr semantisch. Es ist auch eine ziemlich verwirrende Menge an Code im Modell eines Open-Source-Projekts. Vielleicht könnten Sie näher erläutern, warum Mr. Yoshis Idee so schlecht ist? – alt

+2

Keine große Sache, um Methoden zu erstellen, wenn sie sinnvoll sind, viel besser als interne Logik außerhalb des Modells zu setzen. @MrYoshiji Idee ist übrigens gut. – apneadiving

+0

BTW, wie könnte es semantischer sein als '@ challenge.closed?'? – apneadiving