Ich arbeite an einer Rails (derzeit 2.3.4) App, die Subdomains verwendet, um unabhängige Account-Sites zu isolieren. Um es klar zu sagen, was ich meine, ist foo.mysite.com sollte den Inhalt des foo-Accounts anzeigen und bar.mysite.com sollte den Inhalt des Balkens anzeigen.Rails: Best Practice, um Abfragen basierend auf Subdomain abzugrenzen?
Wie können Sie sicherstellen, dass alle Modellabfragen auf die aktuelle Subdomäne beschränkt sind?
Zum Beispiel einer meines Controller sieht ungefähr so aus:
@page = @global_organization.pages.find_by_id(params[:id])
(Hinweis @global_organization
wird im application_controller über Sub-Domain-fu.) Wenn das, was ich würde es vorziehen, ist so etwas wie:
@page = Page.find_by_id(params[:id])
Wenn das Page-Modell gefunden wird, wird automatisch auf die richtige Organisation beschränkt. Ich habe versucht, die default_scope Richtlinie wie folgt aus: (in der Seite Modell)
class Page < ActiveRecord::Base
default_scope :conditions => "organization_id = #{Thread.current[:organization]}"
# yadda yadda
end
(Wieder nur zu beachten, die gleiche application_controller setzt Thread.current [: Organisation] auf die ID der Organisation für den weltweiten Zugang.) Das Problem bei diesem Ansatz besteht darin, dass der Standardbereich bei der ersten Anforderung festgelegt wird und sich bei nachfolgenden Anforderungen an verschiedene Unterdomänen nie ändert.
Drei scheinbare Lösungen so weit:
1 Verwenden Sie separate vhosts für jede Sub-Domain und nur laufen verschiedene Instanzen der App pro Sub-Domain (mit mod_rails). Dieser Ansatz ist für diese App nicht skalierbar.
2 Verwenden Sie den obigen Ansatz des Originalcontrollers. Leider gibt es eine ganze Reihe von Modellen in der App und viele der Modelle sind ein paar Joins aus der Organisation entfernt, so dass diese Notation schnell umständlich wird. Was noch schlimmer ist, ist, dass Entwickler aktiv dazu aufgefordert werden, sich an die Einschränkungen zu erinnern und diese anzuwenden oder ein signifikantes Sicherheitsproblem zu riskieren.
3 Verwenden Sie einen before_filter, um den Standardbereich der Modelle bei jeder Anforderung zurückzusetzen. Sie sind sich nicht sicher, welche Leistung hier erzielt wird oder wie Sie am besten auswählen können, welche Modelle per Update aktualisiert werden sollen.
Gedanken? Irgendwelche anderen Lösungen, die ich vermisse? Dies scheint ein allgemein genug Problem zu sein, dass es eine Best Practice geben muss. Alle Eingaben geschätzt, danke!
Danke für den Input! Haben Sie diesen Code in der Praxis getestet? Ich habe es gerade in der App ausprobiert, und während ich bestätigen kann, dass das Lambda tatsächlich bei jeder Suche ausgewertet wird, wendet das default_scope die zurückgegebenen Werte nicht an. Bei einem Blick auf die Ausgabe-SQL scheinen die Bedingungen einfach ignoriert zu werden. Aus verschiedenen anderen Gründen konnte ich meinen Debugger noch nicht starten, aber ich werde einen Höhepunkt erreichen, sobald er wieder läuft. Gedanken darüber, warum es nicht funktioniert? – qfinder
Ehrlich gesagt habe ich keine Ahnung, wie der interne Server Threads verwendet, also nahm ich an, dass 'Thread.current [: organisation]' im Modell funktionierte. Aber ich weiß nicht, ob das erklären würde, warum die Bedingungen ignoriert werden. Da Sie im Wesentlichen den Standardbereich definieren, nach organazation_id = nil zu suchen. – EmFi
Bei näherer Untersuchung scheint es, dass dies noch nicht funktioniert. Es gibt einen Patch, aber YMMV: https://rails.lighthouseapp.com/projects/8994/tickets/1812-default_scope-cant-take-procs – EmFi