Rails поиск с помощью ActiveRecord ::Relation ИЛИ в ActiveRecord ::Relation

#sql #ruby-on-rails #ruby #ruby-on-rails-3 #activerecord

#sql #ruby-on-rails #ruby #ruby-on-rails-3 #activerecord

Вопрос:

После очень долгого поиска я, наконец, задаю этот вопрос: как мне выполнять ИЛИ обусловливать запросы с помощью ActiveRecord ::Relation в Rails 3.0? В принципе, я считаю, что это должно что-то делать с областью видимости и прочим….

Вот что у меня есть:

 class Practice < ActiveRecord::Base
  attr_accessible :name

  has_and_belongs_to_many :doctors
  has_and_belongs_to_many :services
end

class Doctor < ActiveRecord::Base
  attr_accessible :first_name, :last_name

  has_and_belongs_to_many :practices
  has_and_belongs_to_many :services
end

class Service < ActiveRecord::Base
  attr_accessible :name, :about

  has_and_belongs_to_many :practices
  has_and_belongs_to_many :doctors
end
  

Чего я хочу добиться, так это формы, в которой я могу выполнять поисковые запросы и возвращать объект ActiveRecord::Relation (чтобы я мог использовать его с will_paginate и так далее) со списком практик. Запрос должен найти любую практику, где @practice.name соответствует query_string ИЛИ где @practice.doctors.first_names соответствует query_string ИЛИ где @practice.doctors.last_names соответствует query_string ИЛИ @practice.services.names соответствует query_string. Другими словами, допустим, query_string соответствует имени службы, я хотел бы получить список действий, связанных с этой службой. Или, если first_name или last_name доктора совпадают с query_string, тогда я получаю практики, связанные с этим врачом / врачами. И, конечно, старое доброе совпадение по Practice.name тоже: D

Я понимаю, что мои ассоциации has_and_belongs_to_many здесь не подходят, это просто для демонстрации, но я был бы рад услышать, может ли кто-нибудь помочь с миграциями и ассоциациями для моего случая.

Спасибо.

PS как я уже сказал, я использую Rails 3.0, и я считаю, что он должен что-то делать с областями видимости (но, конечно, я могу ошибаться). Также я пробовал MetaWhere, но не смог заставить его работать …. : (

Комментарии:

1. Я слышал, вы говорили, что хотите это в одном запросе к БД? =P

2. Да, и причина в том, что я мог бы сделать что-то подобное и вернуть, скажем, 3 объекта ActiveRecord ::Relation, но затем, когда я пытаюсь собрать их вместе, они становятся массивом. Как я уже сказал, мне действительно нужно, чтобы он был ActiveRecord::Relation, чтобы я мог использовать его с нумерацией страниц и другими вещами. P.S. не нашел способа создать объект ActiveRecord::Relation из массива.

3. Да Relation , они не работают как представления БД, массив — это массив, и он прямо у вас в оперативной памяти. Ознакомьтесь с моим ответом ниже, надеюсь, он сработает или, по крайней мере, даст вам новую идею!

4. Squeel — это обновленная форма MetaWhere, которую следует использовать для Rails 3.0

Ответ №1:

Давайте посмотрим, как это получается:

 class Practice < ActiveRecord::Base
  class < self
    def by_any_name(param)
      joins(:doctors, :services).
      where(<<-SQL, :name => param)
             doctors.first_name = :name OR
             doctors.last_name  = :name OR
             practices.name     = :name OR
             services.name      = :name
      SQL
    end
  end
end
  

Области действия такие прошлогодние.

И некоторые левые присоединяются к вам (требуется тестирование!):

 joins('LEFT JOIN
         (doctors_practices INNER JOIN doctors
            ON doctors.id = doctors_practices.doctors_id)
          ON doctors_practices.practice_id = practices.id
       LEFT JOIN
         (practices_services INNER JOIN services
            ON services.id = practices_services.service_id)
          ON practices_services.practice_id = practices.id')
  

Блин, мне давно пора спать.

Комментарии:

1. Даст ли это что-нибудь обратно, если у меня будет практика без каких-либо связанных врачей или служб? Спасибо.

2. Нет, только внутренние соединения с этим синтаксисом. Вам нужно левое соединение или что-то в этом роде?

3. да, я думаю, мне нужно что-то вроде левого сустава, потому что даже если я не найду подходящего материала в Службах или у врачей, я все равно хочу получить подходящий материал из Практики. Или, если у меня есть совпадения во всех таблицах, тогда мне нужны все: D, поэтому кажется, что мой большой тренировочный стол находится слева, а два других — справа.

4. спасибо за вашу помощь, но я получаю SQLite3::SQLException: нет такого столбца: doctors_practices.practice_id: ВЫБЕРИТЕ «практика».* ИЗ раздела «практика» Ошибка ЛЕВОГО СОЕДИНЕНИЯ (ActiveRecord::StatementInvalid) с вашим левым соединением. Кроме того, я не думаю, что смогу избежать дублирования результатов с помощью этого запроса, нужно ли мне что-то делать с моими миграциями?

5. Вы можете прочитать имена столбцов из миграций ваших has_and_belongs_to_many таблиц соединений.

Ответ №2:

Вы можете покопаться в ARel ИЛИ — посмотрите, что я там сделал 🙂 — ознакомьтесь с очень удобным gem squeel, который позволяет вам делать именно то, что вы хотите, с хорошим синтаксисом.

https://github.com/ernie/squeel