Как я создаю ленту новостей стиля Facebook в рубине на направляющих?

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

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

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

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

Любая справка значительно ценилась бы, спасибо.

17
задан Cody Brown 11 February 2010 в 03:58
поделиться

3 ответа

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

controller:

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

18
ответ дан 30 November 2019 в 13:05
поделиться

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

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

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

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

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 

и у вас должен получиться объединенный массив.

EDIT #2: Если бы я писал это сам, я бы, вероятно, обрабатывал представления примерно так:

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

render :partial => "item", :collection => @feed

это отобразит частицу '_item.html.erb' для каждого элемента в @feed. Кроме того, каждый раз partial будет передавать локальную переменную с именем 'item', которая является элементом @feed для данной конкретной итерации.

сейчас, вероятно, я бы сделал частицу '_item' очень простой, примерно такой:

<%= display_item(item) %>

где display_item - вспомогательный метод вне представления и реализуется с помощью логики типа "is_a?", описанной выше, чтобы выбрать правильный формат отображения для элемента.

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

1
ответ дан 30 November 2019 в 13:05
поделиться

Как насчет

strsplit(gsub("([[:alnum:]]{2})", "\\1 ", x), " ")[[1]]

В основном, добавьте разделитель (здесь «») и затем используйте strsplit

-121--1026094-

Вероятно, можно было бы сделать лучше, но я сейчас не чувствую себя особенно умным. Это просто чтобы убедиться, что Хаскелл представлен...

Если предположить, что b уже существует, результат будет помещен в w .

import List
a l=2*minimum l-maximum l
z=take 3$unfoldr(Just .splitAt 3)b
w=maximum$0:map a(z++transpose z++[map(b!!)[0,4,8],map(b!!)[2,4,6]])

Предполагая, что вход от stdin и выход к stdout,

import List
a l=2*minimum l-maximum l
w b=maximum$0:map a(z++transpose z++[map(b!!)[0,4,8],map(b!!)[2,4,6]])where
 z=take 3$unfoldr(Just .splitAt 3)b
main=interact$show.w.read
-121--1152320-

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

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

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

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

7
ответ дан 30 November 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: