8 Stimmen

Wiederverwendung von named_scope zur Definition eines anderen named_scope

Das Kernproblem, wie ich es sehe

Eines Tages, wenn ich mich nicht irre, habe ich ein Beispiel für die Wiederverwendung eines named_scope gesehen, um ein anderes named_scope zu definieren. Etwas wie dieses (kann mich nicht an die genaue Syntax erinnern, aber das ist genau meine Frage):

named_scope :billable, :conditions => ...
named_scope :billable_by_tom, :conditions => {
    :billable => true, 
    :user => User.find_by_name('Tom')
}

Die Frage ist: Wie lautet die genaue Syntax, wenn das überhaupt möglich ist? Ich kann es nicht zurückfinden, und Google war auch keine Hilfe.

Einige Erklärungen

Warum ich es eigentlich will, ist, dass ich Searchlogic verwende, um eine komplexe Suche zu definieren, die zu einem Ausdruck wie diesem führen kann:

Card.user_group_managers_salary_greater_than(100)

Aber es ist zu lang, um es überall zu platzieren. Da, soweit ich weiß, Searchlogic einfach named_scopes on the fly definiert, würde ich gerne einen named_scope auf die Klasse Card wie folgt setzen:

named_scope from_big_guys, { user_group_managers_salary_greater_than(100) }

- Hier würde ich die lange Searchlogic-Methode innerhalb meines named_scope verwenden. Aber wie lautet noch einmal die Syntax? Ich kann es nicht herausfinden.

Lebenslauf

Also, ist named_scope Verschachtelung (und ich tue no mean chaining) tatsächlich möglich?

8voto

Oinak Punkte 1785

Sie können verwenden proxy_options um ein named_scope in ein anderes zu recyceln:

class Thing
  #...
  named_scope :billable_by, lambda{|user| {:conditions => {:billable_id => user.id } } }
  named_scope :billable_by_tom, lambda{ self.billable_by(User.find_by_name('Tom').id).proxy_options }
  #...
end

Auf diese Weise kann er mit anderen named_scopes verkettet werden.

Ich verwende dies in meinem Code und es funktioniert perfekt.

Ich hoffe, es hilft.

2voto

Harish Shetty Punkte 63187

Siehe hierzu Frage vor einiger Zeit hier bei SO. Es gibt einen Patch unter Leuchtturm um Ihre Anforderungen zu erfüllen.

2voto

Joshua Pinter Punkte 41335

Rails 3+

Ich hatte die gleiche Frage und die gute Nachricht ist, dass in den letzten fünf Jahren das Rails-Core-Team hat einige gute Fortschritte in der Scopes-Abteilung gemacht.

In Rails 3+ können Sie dies nun tun, wie Sie es erwarten würden:

scope :billable,        where( due: true )
scope :billable_by_tom, -> { billable.where( user: User.find_by_name('Tom') ) }

Invoice.billable.to_sql         #=> "... WHERE due = 1 ..."
Invoice.billiable_by_tom.to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."

_FYI, Rails 3+ haben sie umbenannt named_scope um einfach scope . Ich bin auch mit Ruby 1.9 Syntax._

Bonusrunde: Allgemeiner Anwendungsbereich.

Wenn es neben "Tom" noch weitere Personen gibt, die "abrechenbar" sind, könnte es sinnvoll sein, einen allgemeinen Bereich zu erstellen, der einen Namensparameter akzeptiert, der an den Block übergeben wird:

scope :billable_by, lambda { |name| billable.where( user: User.find_by_name( name ) ) }

Dann können Sie es einfach mit aufrufen:

Invoice.billable_by( "Tom" ).to_sql #=> "... WHERE due = 1 AND user_id = 5 ..."

Übrigens, wie Sie sehen können, habe ich die ältere lambda Syntax in der Bonusrunde. Das liegt daran, dass die neue Syntax meiner Meinung nach grauenhaft aussieht, wenn man ihr einen Parameter übergibt: ->( name ) { ... } .

1voto

Joshua Pinter Punkte 41335

Kettenumfänge.

Warum nicht eine scope für Dinge einfach durch Tom im Allgemeinen, wie:

scope :by_tom, where( user: User.find_by_name('Tom') )

Und dann können Sie die Datensätze abrufen, die von Tom in Rechnung gestellt werden können:

Record.billable.by_tom

0voto

shingara Punkte 45674

Sie können eine Methode verwenden, um einige named_scope wie zu kombinieren:

def self.from_big_guys
  self.class.user_group_managers_salary_greater_than(100)
end

Diese Funktion ist in Rails 3 mit einer neuen Syntax ( http://m.onkey.org/2010/1/22/active-record-query-interface )

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X