如何在rails上的ruby中创建facebook样式的新闻源?

时间:2010-02-11 03:58:59

标签: ruby-on-rails

我正在尝试将对象融合为单个流。

我创建了一个名为Newsfeed的新模型和控制器。我有它所以新闻源has_many:消息和has_many:图像和图像和消息belongs_to:newsfeed。我现在正在设置控制器,我有:

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

如何将它们融合在一起,以便它们可以从两者中拉出来并按时间顺序排列,每个都需要单独制作?

非常感谢任何帮助,谢谢。

3 个答案:

答案 0 :(得分:18)

你可以做一些事情:

控制器:

def index
    messages = Messages.all
    images = Images.all
    @feed = (messages + images).order_by(&:created_at)
end

查看index.html.erb:

<%= render @feed %>

查看_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

答案 1 :(得分:7)

我确信这可以从它的贫民窟多态性中得到简化,但它对我有用,而且我与“我如何结合所有这些模型结果?”进行了相同的斗争?!

我使用像你一样的单独模型和观察者:

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

继续前进我可能会开始将更多内容打包到流跟踪模型中,以便在其他表上保存点击量,但希望你明白这一点。

答案 2 :(得分:1)

这感觉有点像一个问题,虽然我没有时间深入挖掘它,但这里有一些初步的想法:

  1. 您可以将要显示的两种类型的项目组合到一个数组中,然后根据两者之间应该是常见的字段对这个数组进行排序(想到created_at)以使它们按时间顺序排列顺序。

  2. 在视图中,您可以使用此单个集合进行迭代,然后使用帮助程序和唯一的部分来以正确的格式呈现项目。这可以通过在尝试在视图中显示对象类型时检查对象类型来完成。

  3. 有些事情:

    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:如果我自己写这篇文章,我可能会像这样处理这些观点:

    在顶层,只需将您的Feed集合传递给部分,该部分用于呈现单个项目:

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

    这将为@feed中的每个项目呈现'_item.html.erb'部分。此外,它每次都会给部分一个名为'item'的局部变量,这是该特定迭代的@feed中的项。

    现在,我可能会将'_item'部分变得非常简单,就像这样:

    <%= display_item(item) %>
    

    其中display_item是视图外的辅助方法,用“is_a?”实现从上面输入逻辑,为项目选择正确的显示格式。

    我之所以将其分解,是因为它利用了一些漂亮的rails功能(将集合传递给部分而不是自己循环遍历集合)然后将逻辑拉出到帮助器中(甚至是模型,如果这是有道理的)因为它简化了你的观点是有用的。尽可能将逻辑排除在视图之外通常是一种很好的做法,因为这样的逻辑很难测试,你的观点将变得非常难以阅读。