2016-05-23 6 views
1

Es ist meine erste Frage in stackoverflow, weil ich immer finde, was ich brauche, aber nicht dieses Mal. Ich werde meinen Fall erklären ...Wie extrahiert man default_scope query und ruft es in einer has_many-Beziehung auf? - Schienen 4

Ich habe diese Modelle:

class Car < ActiveRecord::Base 
    has_many :rents 
end 

class Rent < ActiveRecord::Base 
    belongs_to :car 
    default_scope { where "end < ?", Time.now } 
end 

Und ihr Schema:

create_table "cars", force: :cascade do |t| 
    t.string "brand" 
    t.string "model" 
    t.string "family" 
    t.decimal "price" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.integer "passengers" 
    t.string "trunk" 
    t.string "doors" 
    t.string "plate" 
    t.string "transmission" 
    end 
    create_table "rents", force: :cascade do |t| 
    t.datetime "start" 
    t.datetime "end" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.integer "car_id" 
    end 

Ich versuche, einen Weg zu finden, die gleichen Ergebnisse zu erhalten, durch Art und Weise der Umfang, dass ich das, wenn ich in meinem Controller-Typ:

def results 
    @cars = Car.all 
end 

ich alle Autos zu bekommen, und jene die Mieten, die ein „Ende“ va haben lue größer als der Param "Time.now", und diejenigen, die keine Miete hat.
Mein Ziel ist es, diese Abfrage etwas ähnlich wie diese Art und Weise zu tun, einen Bereich Aufruf:

def results 
    @cars = Car.available_for_rent 
end 

Jede Hilfe geschätzt wird. Danke im Voraus.

+0

, wenn ich Sie JOIN verwenden das richtig verstanden, ein Auto zur Verfügung, wenn @ car.rents.where ("Start>?", Time.now) .wo ("end lusketeer

+0

Danke für die Antwort @lusketeer. Es gibt mir einen Syntaxfehler, wenn ich es auf eine Ansicht oder meinen Controller setze. Ich versuche alle Autos und deren Mieten zu senden, die die Anfrage vom Controller erfüllen. Das Ziel ist, wie man einen benannten Bereich auf die gleiche Weise aufruft wie default_scope, ohne dass er aufgerufen wird. –

+0

Bienvenido ein stackoverflow – Miguel

Antwort

0

Eigentlich, was ich vorgeschlagen in Kommentar war falsch.

Da Sie die Autos wollen, die verfügbar sind, wir die Autos von der gegenüberliegenden Seite durch Aufsuchen, die derzeit in Miete gehen könnte daher müssen wir die rents sehen, die gültig sind

class Rent < ActiveRecord::Base 
    belongs_to :car 
    scope :active, -> { where("rents.end > ?", Time.now).where("rents.start < ?", Time.now) } 
end 

class Car < ActiveRecord::Base 
    has_many :rents 
    scope :unavailable, -> { joins(:rents).merge(Rent.active) } 
    scope :available, -> { Car.where.not(id: Car.unavailable.pluck("cars.id") } 
end 

eine andere Lösung ist LEFT

class Car < ActiveRecord::Base 
    has_many :rents 
    scope :available, -> { Car.joins("LEFT JOIN (#{Rent.active.to_sql}) ON cars.id = rents.car_id").where("rents.car_id IS NULL") } 
end 
+0

Vielen Dank für die Antwort. Ich habe mehr als ich erwartet, weil Sie mir eine korrekte Art gezeigt haben, über das Problem zu denken, es zu lösen, über Sprache oder Rahmen hinaus Ich brauche noch eine Frage: Ich sehe, dass Ober ist ausführlicher als die andere. Wie auch immer, was wäre besser nach Rails oder Ruby Weg? –

+0

Sie sind willkommen. Ich habe tatsächlich eine andere gemacht Bei einem Fehler in der LINKER JOIN-Abfrage habe ich vergessen, die aktiven Mieten zu filtern. siehe das aktualisierte. Was ist besser, persönlich, bevorzuge ich, was auch immer am schnellsten läuft, deshalb lege ich den LINKEN VERBINDEN einen, da es nur eine Frage ist, aber ich würde den Rest von ihnen im Modell auch für die zukünftige Referenz behalten, die auskommentieren eine, die du nicht benutzt, und die, die du am besten nutzt – lusketeer

0
class Car < ActiveRecord::Base 
    has_many :rents 
    scope :available_for_rent, joins(:rents).where("rents.end < ?", Time.now) 
end 
+0

Danke für die Antwort, @qubit. Ich habe das versucht, aber es wirft mir einen "ArgumentError in StaticController # results", "Der Bereich Körper muss aufrufbar sein". Also, ich wickelte es in eine proc/Lambda " Bereich: available_for_rent, -> (Zeit) { Joins (: Mieten) .where ('ments.end

+0

Np, froh, dass es Ihnen geholfen hat, es zu arbeiten. Können Sie nach den tatsächlichen SQL-Abfragen in der Protokolldatei suchen, während Sie den Bereich aufrufen? – qubit

+0

Danke für Ihre Zeit, @qubit Ich fand die Lösung, die ich brauchte. Danke nochmal. –

Verwandte Themen