Как сделать запрос условным для связанной таблицы в ActiveRecord - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь создать запрос, который будет возвращать отдельные записи из одной таблицы на основе условий в связанной таблице.

В частности, есть модель Act, которая имеет_many Events и, конечно, 'Event' принадлежит__ * Act Я хотел бы найти те Acts, которые не имеют Event на определенную дату.

Запрос должен быть выполнен с условием not, так как в противном случае результаты не исключат никаких записей Act.

Я пробовал различные конструкции, в том числе с использованием методов слияния между классами, но это не сработало.

#Act model
def self.busy_on(date)
    joins(:event).merge.not(Event.busy_on(date))
end
#Event model
def self.busy_on(date)
    where(date: date)
end
#Controller
Act.busy_on(params[:date])

Выше приведена ошибка аргумента (ожидайте, что 1 получил 0), но я не уверен, что это правильно с самого начала.

Ответы [ 4 ]

1 голос
/ 14 мая 2019

Не уверен, что это самый элегантный или «правильный» способ сделать это, но это единственное, что мне удалось сделать:

#Event model
def self.act_busy_on(date)
    where(date: date).pluck(:act_id)
  end
#Act model
def self.available_on(date)
    where.not(id: Event.act_busy_on(date))
  end
#Controller
Act.available_on(params[:date])
0 голосов
/ 15 мая 2019

Вот как я бы порекомендовал пойти по этому поводу.

Мы создадим перевернутые области для занятых и доступных вот так

class Act < ApplicationRecord
   has_many :events 

   scope :busy_on, ->(date) { joins(:events).where(events: {date: date}) }
   scope :available_on, ->(date) {where.not(id: busy_on(date).select(:id))}
end 

Здесь мы создаем одну область для дней, когда Act занят, а затем мы используем эту область в качестве встречного фильтра, чтобы определить, доступно ли действие. Результирующий SQL для busy_on scope будет:

  SELECT 
     acts.* 
  FROM 
     acts
     INNER JOIN events ON acts.id = events.act_id
  WHERE 
     events.date = [THE DATE YOU PASS INTO THE SCOPE]

Таким образом, результирующий SQL для области действия available_on будет:

 SELECT 
   acts.* 
 FROM 
   acts 
 WHERE 
   acts.id NOT IN ( 
      SELECT 
         acts.id
      FROM 
         acts
         INNER JOIN events ON acts.id = events.act_id
      WHERE 
         events.date = [THE DATE YOU PASS INTO THE SCOPE]
   ) 
0 голосов
/ 14 мая 2019

Прежде всего, вам нужно изменить event на events в запросе объединений.

Вы запросили Acts, которые свободны на определенную дату в вашем вопросе, поэтому запрос будет выглядеть так:

def get_acts(date)
    includes(:events).where('events.date = ? and events.id = ?', date, nil)
end

Теперь, если вы позвоните по номеру Act.get_acts(26-05-2019), вы получите действия, которые бесплатны в этот конкретный день.

0 голосов
/ 14 мая 2019
class Act < ApplicationRecord
  def self.busy_on(date)
    #includes(:events).where(events: {created_at: date, id: nil })
   includes(:events).where("events.created_at = ? AND events.id = ?", date, nil)
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...