Как создать ленту новостей в стиле фейсбук в ruby ​​on rails? - PullRequest
17 голосов
/ 11 февраля 2010

Я пытаюсь объединить объекты в один поток.

Я создал новую модель и контроллер под названием Newsfeed. У меня так, что новостная лента has_many: messages и has_many: изображения, а также изображения и сообщения принадлежат: newsfeed Я сейчас настраиваю контроллер, и у меня есть:

def index
    @messages = Messages.all
    @images = Images.all
    @feed = ?
end

Как мне объединить их, чтобы они могли вытянуть их и поместить в хронологическом порядке, когда каждый требует отдельного форматирования?

Любая помощь будет принята с благодарностью, спасибо.

Ответы [ 3 ]

18 голосов
/ 11 февраля 2010

Вы можете сделать что-то как:

контроллер:

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

7 голосов
/ 11 февраля 2010

Я уверен, что это можно упростить из-за гетто-полиморфизма, но это работает для меня, и у меня была идентичная борьба с «как мне объединить все эти результаты модели?!»

Я использую отдельную модель, как вы, и наблюдатель:

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

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

1 голос
/ 11 февраля 2010

Это похоже на загруженный вопрос, и хотя у меня нет времени, чтобы полностью в него разобраться, вот несколько начальных мыслей для вас:

  1. вы можете объединить два типа элементов, которые вы хотите отобразить, в один массив, а затем отсортировать этот массив на основе поля, которое должно быть общим для двух (созданное на ум), чтобы получить их в хронологическом порядке. заказ.

  2. В представлении вы можете использовать эту единственную коллекцию для итерации, а затем использовать помощники и уникальные партиалы для отображения элементов в правильном формате. Это можно сделать, проверив тип объектов, когда вы пытаетесь отобразить его в представлении.

Что-то вроде:

if item.is_a? Message
  render :partial => 'message', :locals => {:message => item }
elsif item.is_a? Image
  render :partial => 'image', :locals => {:image => item }
end

надеюсь, это поможет некоторым!

РЕДАКТИРОВАТЬ: чтобы объединить массивы, вы можете просто добавить их вместе, используя оператор '+', так как массивы в 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?" введите логику сверху, чтобы выбрать правильный формат отображения для элемента.

причина, по которой я бы разбил это на части, заключается в том, что он использует некоторые замечательные функции рельсов (передайте коллекцию в частичную, а не перебирайте коллекцию самостоятельно), а затем извлекайте логику в помощники (или даже модели, если это имеет смысл) полезно, потому что это упрощает ваши взгляды. Хранение логики вне поля зрения всегда, когда это возможно, является хорошей практикой, поскольку такую ​​логику может быть сложно проверить, а ваши представления станут очень трудно читать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...