Prezes Łukasz
Prezes Łukasz

Reputation: 968

Issue with check times overlaps

There are two models:

# 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

I try to create validation that person can join to one activity taking place in specific date and time(start_on, end_on). If I will try sign up to another activity while before I joined to other exercises(same date, and times overlap) should throw error. What I try:

  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

I don't know how to use create query(person.activities.where ...) to getting person activities related with activies_people. activities_date check if we joined to activities taking place in same date. Second I want get check start_on and end_on. Thanks in advance.

Upvotes: 0

Views: 44

Answers (2)

max pleaner
max pleaner

Reputation: 26768

If I'm understanding you correctly, you want to find the activites_people for a user that match a query by the date array and then raise an error unless an associated activity for those matched activities_people.

Your original code for check_join_client uses if incorrectly:

 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

To translate this to pseudocode, you're essentially saying:

result = query if result.condition_met?

However the if condition (the expression after the if) will be evaluated before you define results. It might be more clear if I show a correct approach:

result = query return result if result.condition_met?

Now to go back to your question about loading associated records, try something like this:

   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")

There surely is a way to get this done with one query instead of two, but it seems like where you're at with Ruby concepts it's more important to focus on syntax and core functionality than SQL optimization.

Upvotes: 1

spickermann
spickermann

Reputation: 106922

The correct syntax (one of several options) is:

person.activities_people.where(date: date)

Upvotes: 0

Related Questions