Gibt es eine Möglichkeit der default_scope auszubrechen, wenn has_many mit?
-
02-10-2019 - |
Frage
Ich habe ein baumartiges Modell, bei dem in alle Situationen aber ein , ich möchte, die Ergebnisse zu Umfang, um nur die Wurzeln zurückzukehren.
class Licence < ActiveRecord::Base
default_scope :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences
end
Mit default_scope
wie eine wunderbare Idee schien, weil die verschiedenen Modelle, die Assoziationen Lizenz haben (es etwa 4 von ihnen sind) und auch beliebigen Code mit find (), würde nichts Besonderes tun muss. Der Grund ist es nicht eine wunderbare Idee ist, dass der Standardbereich gilt auch für die has_many
, die Ergebnisse in nie die Kinder zu finden. Aber die has_many
ist die nur Ort, der den Rahmen sprengen muss aus, so weit wie „default“ Verhalten geht, ich denke, das default_scope
durchaus sinnvoll ist.
So gibt es eine gute Möglichkeit, dieses spezielle Problem zu umgehen?
Hier ist eine, die ich bin nicht allzu gern, weil es verwendet SQL für eine fast triviale Abfrage:
has_many :nested_licences, :class_name => 'Licence', :dependent => :destroy,
:finder_sql => 'SELECT l.* FROM licences l WHERE l.parent_licence_id = #{id}',
:counter_sql => 'SELECT COUNT(l.*) FROM licences l WHERE l.parent_licence_id = #{id}'
Alternativ ist es eine Möglichkeit, einen benannten Rahmen eine Vereinigung aus dem Modell zu bewerben? z.B. etwas entlang der Linien von diesem Unsinn-Code:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :scope => :roots # a :scope option doesn't really exist
end
Ich weiß, ich kann dies auch tun:
class Licence < ActiveRecord::Base
named_scope :roots, :conditions => { :parent_licence_id, nil }
belongs_to :parent_licence, :class_name => 'Licence'
has_many :nested_licences, :class_name => 'Licence',
:foreign_key => 'parent_licence_id', :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :licences, :conditions => { :parent_licence_id, nil }
end
Aber das ist wirklich nicht sehr trocken ist. Eigentlich statt Licence.roots.find()
jede einzelne Abfrage durch Licence.find()
zu tun hat, ist nicht sehr trocken entweder, um ehrlich zu sein. Es ist nur für einen Fehler zu fragen vor, wenn der Umfang nicht verwendet wird.
Lösung
Versuchen Licence.unscoped.find()
mit
btw -
Die Dokumentation für ActiveRecord::Base.unscoped
sagt, dass unscoped
mit einer benannten scope
Methode Verkettungs keine Wirkung.
Es wird empfohlen, die Blockform unscoped
zu verwenden, da mit einem benannten unscoped
scope
Verkettungs nicht funktioniert. Wenn „gesendet“ (unten) ist ein named_scope die beiden folgenden Anweisungen sind die gleichen.
Message.unscoped.sent
Message.sent
Schienen FYI 2 hat auch with_exclusive_scope
, die hilfreich sein können.
Andere Tipps
Können Sie keinen Gebrauch von der :conditions
Option über die Assoziation machen? So etwas wie folgt aus:
has_many :nested_licences, :class_name => 'Licence',
:dependent => :destroy, :conditions => "parent_licence_id = #{id}"