Итак, я пытаюсь создать возможность поиска встреч в своем приложении, и у меня возникают проблемы с дублированием записей и упорядочиванием.
Подводя итог:
Встреча проводится между двумя пользователями, один из которых - booker
, а другой - bookee
. Встреча также has_many :time_options
, которую пользователь может предложить, а затем, когда bookee
выбирает и подтверждает одну из предложенных time_options
, start_time
применяется к аналогичному атрибуту start_time
встреч. Модели структурированы следующим образом:
#appointment.rb
belongs_to :booker, foreign_key: :booker_id,
class_name: 'Profile'
belongs_to :bookee, foreign_key: :bookee_id,
class_name: 'Profile'
has_many :time_options, dependent: :destroy
scope :order_by_start_time, -> {
joins(:time_options)
.order("COALESCE(appointments.start_time, time_options.start_time) DESC")
}
def self.search(search)
if search
search_term = "%#{search}%"
joins(
"INNER JOIN profiles ON profiles.id IN (appointments.booker_id,
appointments.bookee_id)"
)
.where(
"CONCAT_WS(' ', profiles.first_name, profiles.last_name) ILIKE :term
OR appointments.service_title ILIKE :term",
term: search_term
)
else
where(nil)
end
end
#time_option.rb
belongs_to :appointment, touch: true
belongs_to :profile
#profile.rb
belongs_to :user, touch: true
has_many :booker_appointments, foreign_key: :booker_id,
class_name: 'Appointment',
dependent: :nullify
has_many :bookee_appointments, foreign_key: :bookee_id,
class_name: 'Appointment',
dependent: :nullify
Я пытаюсь разрешить пользователям искать встречи по номеру service_title
или имени другого пользователя (независимо от того, booker
или bookee
). Затем я хочу упорядочить эти результаты поиска по start_time
. Либо start_time
самой встречи (которая устанавливается только при подтверждении встречи), либо, если встреча еще не подтверждена, и это start_time
равно nil
, вместо этого используйте самое раннее start_time
связанных time_options
.
Итак, в контроллере я делаю что-то вроде:
def index
@appointments = Appointment.all_profile_appointments(@profile)
if params[:search]
@upcoming_appointments = @appointments.search(params[:search])
.order_by_start_time
.page(params[:page])
.per(12)
else
@upcoming_appointments = @appointments.order_by_start_time
.page(params[:page])
.per(12)
end
end
Однако мой метод поиска возвращает дубликаты, я полагаю, из-за INNER JOIN
. И если я добавлю .distinct
до или после order_by_start_time method
, я получу замечательную ошибку: PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
Так что я почти уверен, что мне просто нужно написать более сложный и точный оператор SQL ; но, между необходимостью присоединения к таблице profiles
для поиска по имени, необходимостью присоединения / объединения таблицы time_options
для упорядочивания по start_time
, я не совсем уверен, где делать go дальше. В качестве фона я использую postgresql
и Rails 4.
TL; DR: я пытаюсь найти записи о встречах по имени профиля, который забронировал или был забронирован для встречи. Затем я хочу заказать этот запрос по appointments.start_time
или, если время начала встречи не подтверждено, то по самому раннему time_options.start_time
, связанному с встречей. И я пытаюсь обойтись без кучи повторяющихся записей.