2009-04-27 3 views
4

Ich arbeite an einer Multi-User-App mit mehreren Accounts, bei der ein Account n Nutzer haben kann. Es ist sehr wichtig, dass jeder Benutzer nur auf Informationen von seinem Konto zugreifen kann. Mein Ansatz besteht darin, jedem Modell in der DB eine account_id hinzuzufügen und dann in jedem Controller einen Filter hinzuzufügen, um nur Objekte mit der aktuellen account_id auszuwählen. Ich werde das Autorisierungs-Plugin verwenden.Wie wird immer ein Wert für account-scope in Rails festgelegt?

Ist dieser Ansatz eine gute Idee?

Was ist der beste Weg, um immer die account_id für jedes Objekt festlegen, ohne das Schreiben

object.account = @current_account 

in jeder Aktion CREATE erstellt wird? Vielleicht ein Filter?

Auch bin ich mir nicht sicher über die beste Möglichkeit, den Filter für die Auswahloptionen zu implementieren. Ich brauche etwas wie eine allgemeine Bedingung: Egal was sonst in der SQL-Anweisung erscheint, es gibt immer ein "WHERE account_id = XY".

Danke für Ihre Hilfe!

Antwort

4

Dies ähnelt einem Szenario Users.has_many: emails. Sie wollen nicht, den Benutzer andere Völker E-Mails, um zu sehen, indem Sie die ID in der URL zu ändern, so können Sie dies tun:

@emails = current_user.emails 

In Ihrem Fall, werden Sie wahrscheinlich so etwas tun kann:

class ApplicationController < ActionController::Base 
    def current_account 
    @current_account ||= current_user && current_user.account 
    end 
end 

# In an imagined ProjectsController 
@projects = current_account.projects 
@project = current_account.projects.find(params[:id]) 
+0

Well Ich könnte das tun und meine current_account-Methode verwenden, aber dann muss ich jede Aktion ändern. Gibt es keinen einfacheren Weg? Ich habe sogar darüber nachgedacht, die Methode find/create zu patchen, weil ich immer den gleichen Wert einstelle (für einen angemeldeten Benutzer). –

+0

Tun Sie es in jeder Aktion ist kein Problem. Es ist ein einmaliger Versuch, und es dauert 5 Minuten. Es macht auch Ihren Code leicht zu verstehen - es ist genau dort, Sie müssen nicht auf die Abstraktionen schauen. –

+1

Es ist ein wenig mehr als 5 Minuten, aber nach einer Menge Ärger und Monkeypathing mit meiner Lösung werde ich es einfach auf die Schienen machen. Vielen Dank. –

1

Ich weiß, ich weiß, wenn Sie auf Sitzungsvariablen oder Instanzvariablen in Ihrem Modell zugreifen, haben Sie das MVC-Muster nicht verstanden und sollten "zurück zu PHP gehen". Aber auch das kann sehr nützlich sein, wenn Sie - wie wir - viele Controller und Aktionen haben, bei denen Sie nicht immer @ current_account.object.do_something schreiben möchten (nicht sehr DRY).

Die Lösung fand ich sehr einfach:

Schritt 1: Fügen Sie Ihre current_account zu Thread.current, so zum Beispiel

class ApplicationController < ActionController::Base 
    before_filter :get_current_account  

    protected 
    def get_current_account 
    # somehow get the current account, depends on your approach 
    Thread.current[:account] = @account 
    end 
end 

Schritt 2: eine current_account Methode auf alle Ihre Modelle hinzufügen

#/lib/ar_current_account.rb 
    ActiveRecord::Base.class_eval do 
    def self.current_account 
     Thread.current[:account] 
    end 
    end 

Schritt 3: voilà, in Ihren Modellen können Sie etwas tun:

Sie könnten auch mit etwas wie dem before_validation Callback in active_record arbeiten und dann mit einer Validierung sicherstellen, dass das Konto immer gesetzt ist.

Derselbe Ansatz kann verwendet werden, wenn Sie den current_user immer zu jedem erstellten Objekt hinzufügen möchten.

Was denkst du?

+1

Wie ich oben erwähnt habe, ist es kein Problem, es in jeder Aktion anzugeben. Es ist ein einmaliger Job, und es dauert nicht lange. –

1

Um Ihre zweite Frage zu beantworten, sehen Sie sich die neue Funktion default_scope in Rails 2.3 an.

+0

groß, genau was ich brauchte! –

1

Ich verstehe, dass Sie sich nicht darum kümmern wollen, Ihr Konto jederzeit zu bestimmen. Lass uns ehrlich sein, es ist ein Schmerz in der a **.

Um ein wenig Magie hinzuzufügen und diese Scoping nahtlos einen Blick auf die folgenden gem

http://gemcutter.org/gems/account_scopper

hoffe, das hilft,

geben getan haben - Sébastien Grosjean - ZenCocoon

+0

Einige Kombination von SO/Firefox bedeutet, dass Link für mich nicht funktioniert - es 404s. Alternativer Link zum selben Ort: http://is.gd/4SyvE – NeilS

+0

Danke für die URL fix NeilS. –