2016-08-05 14 views
0

Es gibt zwei Modelle:Ausgabe mit Prüfzeiten überlappt

# Table name: activities_people 
# 
# activity_id :integer   not null 
# person_id :integer   not null 
# date  :date    not null 
# id   :integer   not null, primary key 

# == Schema Information 
# 
# Table name: activities 
# 
# id   :integer   not null, primary key 
# name  :string(20)  not null 
# description :text 
# active  :boolean   not null 
# day_of_week :string(20)  not null 
# start_on :time    not null 
# end_on  :time    not null 

Relations: activity.rb

has_many :activities_people 
has_many :people, through: :activities_people 

activity_people.rb

belongs_to :person 
belongs_to :activity 

Ich versuche Validierung zu erstellen, die Person kann zu einer Aktivität hinzukommen, die an einem bestimmten Datum und zu einer bestimmten Uhrzeit stattfindet (start_on, end_on). Wenn ich versuche, mich zu einer anderen Aktivität anzumelden, bevor ich mich anderen Übungen angeschlossen habe (dasselbe Datum und Zeiten, die sich überschneiden), sollte der Fehler ausgelöst werden. Was ich versuche:

def check_join_client 
    activities_date = person.activities_people.where('date = date', date: date) 
    if activities_date.exists && person.activities.where('id IN (?)', activities_date) 
    end 

Ich weiß nicht, wie Abfrage erstellen verwenden (person.activities.where ...) Person Aktivitäten mit activies_people Bezug zu bekommen. activities_date überprüft, ob wir uns Aktivitäten angeschlossen haben, die am selben Tag stattfinden. Zweitens möchte ich check start_on und end_on bekommen. Vielen Dank im Voraus.

+0

Einfache Möglichkeit zu tun "where in" ist ein Array zur Verfügung stellen: dh 'User.where (id: [1,2,3])' –

+0

@maxpleaner ok Ich verstehe, aber wie man person.activities id überprüfen (Aktivität ID nicht Person) ist Inactivities_Date Ergebnis? –

Antwort

1

Wenn ich Sie richtig bin zu verstehen, können Sie die activites_people für einen Benutzer zu suchen, die eine Abfrage nach dem Datum Array entsprechen und dann erhöhen ein Fehler, es sei denn, eine zugehörige activity für diese übereinstimmte activities_people.

Ihr Original-Code für check_join_client verwendet if falsch:

def check_join_client 
    activities_date = person.activities_people.where('date = date', date: date) 
    if activities_date.exists && person.activities.where('id IN (?)', activities_date) 
    end 

dies zu Pseudo-Code zu übersetzen, sind Sie im Wesentlichen sagen:

result = query if result.condition_met? 

jedoch der if Zustand (der Ausdruck nach den if) wird ausgewertet, bevor Sie results definieren. Es könnte klarer sein, wenn ich einen korrekten Ansatz zeige:

Ergebnis = Abfrage Ergebnis zurückgeben, wenn result.condition_met?

Nun zu Ihrer Frage über das Laden verbunden sind Aufzeichnungen zurück zu gehen, versuchen, etwas wie folgt aus:

activities_people_ids_matching_date = person.activities_people 
               .where(date: self.date) 
               .pluck(:id) 
    # use pluck to get an array of ids because that's all that's needed here 
    # not sure how you're getting the date variable, so I'm assuming self.date will work 
    # I can use `.any?` to see if the ids list is not empty. 
    condition_met = activities_people_ids_matching_date.any? &&\ 
        person.activities 
         .where(activities_people_id: activities_people_ids_matching_date) 
         .any? 
    condition_met ? true : raise(StandardError, "my error") 

Es ist sicherlich eine Möglichkeit, dies mit einer Abfrage statt zwei zu erledigen, aber es scheint, wie, wo Sie Bei Ruby-Konzepten ist es wichtiger, sich auf Syntax- und Kernfunktionen als auf SQL-Optimierung zu konzentrieren.

+0

ist das nicht alles korrekt, weil ich jetzt nicht zu einer anderen Aktivität am gleichen Datum teilnehmen kann. Wir sollten auch mal nachschauen.E.G. Erste Aktivität: 05.08.2016 8:00 - 9:00 Zweite Aktivität: 05.08.2016 9:00 - 10:00 - korrekt. Zweiter 05.08.2016 8:00 - 9:00, 05.08.2016 8:30 - 9:30 - falsch. –

+0

nicht wirklich klar ...Versuchen Sie, eine Anzahl von Zeiten in der Abfrage zu verwenden, d. h. von 9 Uhr morgens bis 10 Uhr morgens? –

+0

Wie folgt: ''((start_on <=: start_on UND end_on> =: end_on) ODER (start_on <=: start_on UND end_on <=: end_on ...)' –

0

Die korrekte Syntax (eine von mehreren Optionen) ist:

person.activities_people.where(date: date) 
+0

Ihr Code löst kein Ergebnis aus. Aber wenn ich nach der aktuellen Person suche 'person.activities_people.where (person_id: 2)' sind 2 activities_people mit demselben Datum ... –