Как создать ленту новостей в стиле facebook в рубине на рельсах?
Я пытаюсь подключиться к объектам в один поток.
Я создал новую модель и контроллер под названием Newsfeed. У меня это так, что newsfeed has_many: messages и has_many: изображения и изображения и сообщения принадлежат_to: newsfeed. Я настраиваю контроллер прямо сейчас, и у меня есть:
def index
@messages = Messages.all
@images = Images.all
@feed = ?
end
Как я их сплавляю, чтобы он мог вытащить из обоих и поставить их в хронологическом порядке, когда каждый из них требует отдельного форматирования?
Любая помощь будет принята с благодарностью, спасибо.
Ответы
Ответ 1
Вы можете сделать что-то как:
:
def index
messages = Messages.all
images = Images.all
@feed = (messages + images).order_by(&:created_at)
end
view index.html.erb:
<%= render @feed %>
view _feed.html.erb:
<% if feed.is_a? Message %>
<%= render "message", :locals => {:message => feed}%>
<% else %>
<%= render "image", :locals => {:image => feed}%>
<% end %>
И добавьте 2 частичных _message.html.erb и _image.html.erb
Ответ 2
Я уверен, что это может быть упрощено из-за этого гетто-полиморфизма, но оно работает для меня, и я столкнулся с одинаковой борьбой с "как мне объединить все эти результаты модели?!"
Я использую отдельную модель, например, вы и наблюдатель:
class NewsfeedObserver < ActiveRecord::Observer
observe Message, Image
def after_save(object)
@item = Newsfeed.create(
:item_id => object.id,
:item_type => object.class.to_s
)
end
end
Затем в модели Newsfeed вы можете вытягивать и сортировать по своему усмотрению:
def self.get_items
item_list = []
items = find(:all, :order => "created_at DESC", :limit => 30)
items.collect{ |i| i.item_type.constantize.find(i.item_id) }
end
Затем просто потяните их и покажите в своем представлении, как вам нравится.
#Controller
def index
@feed = Newsfeed.get_items
end
Двигаясь вперед, я, вероятно, начну собирать больше в модель отслеживания потоков, чтобы сохранять хиты на других таблицах, но, надеюсь, вы получите эту идею.
Ответ 3
Это кажется немного загруженным вопросом, и, хотя у меня нет времени полностью вникать в это, вот несколько начальных мыслей для вас:
-
вы можете объединить два типа элементов, которые хотите отобразить, в один массив, а затем отсортировать этот массив на основе поля, которое должно быть общим между двумя (created_at приходит на ум), чтобы получить их в хронологическом порядке порядок.
-
В представлении вы можете использовать эту единую коллекцию для перебора, а затем использовать хелперы и уникальные частичные части для рендеринга элементов в правильном формате. Это можно сделать, проверив тип объектов, когда вы пытаетесь отобразить его в представлении.
Что-то по строкам:
if item.is_a? Message
render :partial => 'message', :locals => {:message => item }
elsif item.is_a? Image
render :partial => 'image', :locals => {:image => item }
end
надеюсь, это поможет некоторым!
EDIT: чтобы объединить массивы, вы можете просто добавить их вместе, используя оператор "+", поскольку массивы в Ruby не должны содержать один тип объекта.
ваши вызовы Messages.all и Images.all дают вам массивы объектов, поэтому просто попробуйте
@messages + @images
и вы должны иметь объединенный массив.
РЕДАКТИРОВАТЬ № 2: Если бы я сам писал это, я бы, вероятно, обработал взгляды примерно так:
на верхнем уровне, просто передайте свою коллекцию фидов части, которая предназначена для рендеринга одного элемента:
render :partial => "item", :collection => @feed
это приведет к частичной части '_item.html.erb' для каждого элемента в @feed. Кроме того, он будет давать частичную локальную переменную с именем "item" каждый раз, которая является элементом в @feed для этой конкретной итерации.
теперь, я бы, наверное, частичный "_item" был очень простым, например:
<%= display_item(item) %>
где display_item является вспомогательным методом вне представления и реализуется с помощью "is_a?" тип выше, чтобы выбрать правильный формат отображения для элемента.
причина, по которой я сломался, так это то, что она использует некоторые полезные функции рельсов (передайте коллекцию частичной, а не зацикливая на коллекцию), а затем вытащить логику в помощники (или даже модели if это имеет смысл) полезно, потому что это упрощает ваши взгляды. логика из соображений, когда это возможно, является, как правило, хорошей практикой, поскольку такую логику трудно тестировать, и ваши взгляды станут очень трудными для чтения.