Eine vorhandene Rails 2.3.x-App mit einem benutzerdefinierten rollenbasierten Autorisierungssystem wird beibehalten.Rails hattm: gibt verknüpfte Datensätze zurück, aber mit ausschließlicher Übereinstimmung
Der Code hat etwas Ähnliches:
class Role << AR:Base
# has an int attribute called "level" with higher values indicating more powerful role
habtm: members
end
class Member << AR:Base
habtm: roles
end
Tabelle Rollen hat so etwas wie
(id, name, level)
1, admin, 1000
2, VIP, 500
3, regular, 100
4, some_other_role, 50
Ich habe folgende Mitglieder mit genannten Rollen
member1 (Rollen: admin
, VIP
, regular
)
member2 (Rollen: VIP
, regular
)
member3 (Rollen: regular
)
Was ich manchmal noch Mitglieder Pull-up auf der Grundlage ihrer höchsten zugewiesen Rolle:
Role.admins_exclusively # should return member1
Role.vips_exclusively # should return just member2
Role.regulars_exclusively # should be just member3
Kann meinen Kopf um nicht umgebrochen, wie dies zu tun in Rails, ohne Abfragen zu schreiben rohe SQL greifen zu müssen.
Irgendwelche Vorschläge?
Update: 29. März 2012
Dies war meine Lösung im Grunde eine Reihe von Methoden wie folgt definieren (auch einige dynamische Programmierung zusammen mit define_method() verwendet wird) für jede Rolle.
class Member < AR:Base
define_method :vips_exclusively do
scoped :joins => :roles,
:group => 'members.id',
:having => ["max(roles.level) = ?", Role.find_by_name('vip').level]
end
end
Allerdings habe ich festgestellt, dass es ein Problem mit älteren Schienen 2.3.x gibt. Das Aufrufen von size() oder count() auf Member.vips_exclusively würde beispielsweise zu falschen Summen führen. Calling length() würde das korrekte Ergebnis liefern, aber es wird empfohlen, size() zu verwenden, wo immer es möglich ist.
Nach dem Blick auf Rails-Code, es sieht aus wie Optionen wie :group
und :having
nicht weitergegeben werden, um count() wenn im Bereich() festgelegt. Ersetzen von Aufrufen von scoped() mit named_scopes (update: DOES NOT) lösen das Zählproblem.
Also habe ich Chris 'Vorschlag zusammen mit einigen Bearbeitungen für die Korrektheit/Kürze übernommen. Vielen Dank!
Ein weiteres Update.
Tatsächlich ist das Problem von: group und: nicht übergeben wurde auch in named_scoped Implementierung.
Und sicher genug, hier ist ein veraltetes Ticket ohne Fehler, der es jemals in den Quellbaum von Rails geschafft hat (zumindest nicht in der 2.3.x-Verzweigung).
https://rails.lighthouseapp.com/projects/8994/tickets/1349-named-scope-with-group-by-bug
Das ist großartig ...