У меня есть сложная таблица, вытащенная из массива объектов multi-ActiveRecord. Этот список представляет собой комбинированный показ всех «любимых» предметов определенного пользователя (песни, сообщения, сообщения в блогах, что угодно). Каждый из этих элементов является полноценным объектом AR.Сортировка/разбиение на страницы/многокомпонентные многоуровневые таблицы объектов в рельсах
Моя цель - предоставить пользователю упрощенный интерфейс поиска, сортировки и разбивки на страницы. Пользователь не должен знать, что у песни есть певец и что у сообщения есть автор - для конечного пользователя обе записи в таблице будут отображаться как «Пользователь». Таким образом, поле поиска будет просто выпадающим списком с запросом на поиск (имя пользователя, созданное на и т. Д.). Внутри мне нужно было бы преобразовать это в соответствующий поиск объектов, объединить результаты и отобразить.
Я могу, отдельно, разбивать на страницы (mislav will_paginate), сортировать и фильтровать, но вместе у меня возникают проблемы с их объединением.
Например, если я разбиваю на страницы комбинированный список элементов, плагин для разбивки на страницы обрабатывает его просто отлично. Это неэффективно, так как разбиение на страницы происходит в приложении или в базе данных, но предположим, что предполагаемый прецедент указывает, что подавляющее большинство пользователей будут иметь менее 30 привилегированных элементов и все другие действия, возможности сервера и т. Д. указывает, что это не будет узким местом.
Однако, если я хочу сортировать список, я не могу сортировать его через плагин для разбивки на страницы, потому что он полагается на предположение, что результирующий набор получен из одного SQL-запроса, а также что имя поля согласовано во всем. Таким образом, я должен сортировать объединенный массив через ruby, например.
@items.sort_by{ |i| i.whatever }
Но, так как элементы не имеют общие названия, я должен сначала допросить объект, а затем вызвать правильную сортировку. Например, если пользователь хочет сортировать по имени пользователя, если отсортированный объект является сообщением, я сортирую по автору, но если объект является песней, я сортирую певцом. Все это очень грубо и выглядит совсем не-рубиново.
Эта же проблема вступает в игру с фильтром. Если пользователь фильтрует «родительский элемент» (поток сообщения, альбом песни), я должен перевести его на соответствующий метод объекта коллекции. Также брутто.
Это не точная настройка, но достаточно близко. Обратите внимание, что это устаревшее приложение, поэтому его изменение довольно сложно, хотя и невозможно. Кроме того, да, есть некоторые СУХИЕ, которые можно сделать, но не фокусируйтесь на стиле или элегантности следующего кода. Стиль/элегантность решения важны, однако! : D
модели:
class User < ActiveRecord::Base
...
has_and_belongs_to_many :favorite_messages, :class_name => "Message"
has_and_belongs_to_many :favorite_songs, :class_name => "Song"
has_many :authored_messages, :class_name => "Message"
has_many :sung_songs, :class_name => "Song"
end
class Message < ActiveRecord::Base
has_and_belongs_to_many :favorite_messages
belongs_to :author, :class_name => "User"
belongs_to :thread
end
class Song < ActiveRecord::Base
has_and_belongs_to_many :favorite_songs
belongs_to :singer, :class_name => "User"
belongs_to :album
end
контроллер:
def show
u = User.find 123
@items = Array.new
@items << u.favorite_messages
@items << u.favorite_songs
# etc. etc.
@items.flatten!
@items = @items.sort_by{ |i| i.created_at }
@items = @items.paginate :page => params[:page], :per_page => 20
end
def search
# Assume user is searching for username like 'Bob'
u = User.find 123
@items = Array.new
@items << u.favorite_messages.find(:all, :conditions => "LOWER(author) LIKE LOWER('%bob%')")
@items << u.favorite_songs.find(:all, :conditions => "LOWER(singer) LIKE ... ")
# etc. etc.
@items.flatten!
@items = @items.sort_by{ |i| determine appropriate sorting based on user selection }
@items = @items.paginate :page => params[:page], :per_page => 20
end
вид:
#index.html.erb
...
<table>
<tr>
<th>Title (sort ASC/DESC links)</th>
<th>Created By (sort ASC/DESC links))</th>
<th>Collection Title (sort ASC/DESC links)</th>
<th>Created At (sort ASC/DESC links)</th>
</tr>
<% @items.each |item| do %>
<%= render { :partial => "message", :locals => item } if item.is_a? Message %>
<%= render { :partial => "song", :locals => item } if item.is_a? Song %>
<%end%>
...
</table>
#message.html.erb
# shorthand, not real ruby
print out message title, author name, thread title, message created at
#song.html.erb
# shorthand
print out song title, singer name, album title, song created at
Мне нравится, но установка поисковой системы для этой маленькой функции кажется излишней (поскольку она не является триалом для запуска сфинкса и т. Д.) –
Срок действия вашего домена истек. –