Соберите сложный SQL-запрос, используя Activerecord::Relation и/или Arel с 'соединениями', 'как' и 'подобно'

Я создаю приложение rails 3.2, используя таблицы данных (http://datatables.net) с пейджингом на стороне клиента и фильтрацией на большинстве html-таблицы, пейджинг и фильтрация на стороне сервера в некоторых других html-таблицах. Я хочу выполнить фильтрацию по столбцам, что очень просто для клиентских таблиц, но я думаю, что мне нужно создать SQL-запрос для базы данных, чтобы выполнять фильтрацию по столбцам для серверных таблиц. Я внимательно следил за примером из RailsCast #340 по таблицам данных и добился того, что это сработало.

Задача заключается в сортировке и фильтрации столбца, который на самом деле является отношением Foreign_key к другой таблице. Я не хочу сортировать и фильтровать фактическое содержимое значений Foreign_key. Я хочу отсортировать и отфильтровать значения «.to_s», отображаемые для связанных объектов (что является семантикой использования функции сортировки и фильтрации на стороне клиента). Вот пример:

class Address < ActiveRecord::Base
  attr_accessible :city, :line1, :line2, :state, :zip

  has_many :people

  def to_s
    [line1, line2, city, state, zip].join(' ')
  end
end
class Person < ActiveRecord::Base
  attr_accessible :address, :name

  belongs_to :address
end

поэтому представление, отображающее список людей, имеет два столбца, для имени и адреса.

<td><%= p.name %></td>
<td><%= p.address %></td>

и то, что появляется в таблице индексов,

John Smith |  1234 Main St Anywhere City AA 12345

таким образом, с помощью сортировки и фильтрации на стороне клиента я могу выполнить поиск «Где угодно» в столбце адреса и получить все строки с этим термином в поле адреса. Делать то же самое на стороне сервера кажется намного сложнее. Я думаю, что пытаюсь собрать sql-запрос, который выглядит примерно так:

select * from people 
         join address on people.address_id = address.id
        where concat(address.line1, 
                     address.line2, 
                     address.city, 
                     address.state, 
                     address.zip) as spec_address like query_term 
     order by spec_address

(Это не обязательно правильный код SQL.)

Я безуспешно просматривал как руководство ActiveRecord Query Rails, так и все, что мог найти на Arel.


person user2434753    schedule 30.05.2013    source источник


Ответы (1)


Вы можете сделать это с областью действия Address, которая затем объединяется с запросом Person.

class Address < ActiveRecord::Base
  scope :anywhere, lambda{|search|
    attrs = [:line1, :line2, :city, :state, :zip]
    where(attrs.map{|attr| "addresses.#{attr} LIKE :search"}.join(' OR '), search: "#{search}%").
      order(*attrs) 
  }
end

Person.joins(:address).merge(Address.anywhere(query_term))
person PinnyM    schedule 30.05.2013
comment
Спасибо! К вашему сведению, Person.includes(:address).merge(Address.anywhere(query_term)) не создает объединение на person.address_id = address.id, а Person.joins(:address).merge(Address.anywhere(query_term)) делает то, что я хочу. - person user2434753; 31.05.2013