Предложение «Где» с объединенными полями в Rails 3 - PullRequest
1 голос
/ 08 декабря 2010

Я пишу приложение rails 3, и у меня есть таблица базы данных Users. У пользователей есть столбцы first_name и last_name. На моей странице со списком пользователей я хочу иметь одно текстовое поле поиска, которое позволяет пользователю фильтровать список. Они должны иметь возможность ввести в поле поиска одно из следующих действий: - имя пользователя - Фамилия пользователя - полное имя пользователя (например, «Smith, John»)

Я не знаю, как написать предложение where, которое будет возвращать эти результаты. Ближайшее, что я получил, находится ниже, однако часть объединенных полей не работает.

where('(first_name LIKE :search) or (last_name LIKE :search) or ("#{last_name}, #{first_name}" LIKE :search)', :search => "%#{search}%")

Мне также интересно узнать, есть ли лучший способ обработать мои операторы OR, поскольку этот пункт становится довольно неуклюжим.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 04 февраля 2011

В случае, если это кому-нибудь еще поможет, я выбрал следующее решение:

  def self.search(query)
    if query.blank?
      scoped
    else
      sql = query.split.map do |word|
       %w[first_name last_name].map do |column|
        sanitize_sql ["#{column} LIKE ?", "%#{word}%"]
       end.join(" or ")
      end.join(") and (")
      where("(#{sql})")
    end
  end

Спасибо Райану Бейтсу из Railscasts за это решение.

2 голосов
/ 08 декабря 2010

Вы должны помнить, что where превратится в SQL, и если вы хотите сравнить составные столбцы с поисковой строкой, вы должны сделать это на уровне базы данных / sql.

Теперь этовот где это сложно, потому что конкатенация в sql отличается в зависимости от вашей базы данных.

В Postgresql и Oracle вы могли бы написать что-то вроде:

where("(first_name LIKE :search) or (last_name LIKE :search) or (last_name || ',' || first_name LIKE :search)", :search => "%#{search}%"

К сожалению, Mysql не поддерживает стандартную конкатенациюоператор ||, с mysql вы должны будете использовать concat вместо:

where("(first_name LIKE :search) or (last_name LIKE :search) or (concat(last_name, ',', first_name) LIKE :search)", :search => "%#{search}%"
...