【问题标题】:How do I create a facebook style news feed in ruby on rails?如何在 ruby​​ on rails 中创建 facebook 风格的新闻提要?
【发布时间】:2010-02-11 03:58:59
【问题描述】:

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

我创建了一个名为 Newsfeed 的新模型和控制器。我有它,以便新闻提要 has_many :messages 和 has_many :images 以及图像和消息属于_to :newsfeed。我现在正在设置控制器,我有:

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

当每个都需要单独格式化时,我如何融合它们以便它可以从两者中提取并按时间顺序排列它们?

任何帮助将不胜感激,谢谢。

【问题讨论】:

标签: ruby-on-rails


【解决方案1】:

你可以这样做:

控制器:

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

【讨论】:

【解决方案2】:

我确信这可以从它的 ghetto-polymorphism 中简化,但它对我有用,而且我对“我如何结合所有这些模型结果?!”也有同样的挣扎。

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

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】:

    这感觉有点像一个加载的问题,虽然我没有时间深入研究它,但这里有一些初步的想法给你:

    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
    

    希望这对一些人有所帮助!

    编辑:要组合数组,您可以使用“+”运算符简单地将它们附加在一起,因为 Ruby 中的数组不需要包含单个对象类型。

    您的 Messages.all 和 Images.all 调用会为您提供对象数组,因此请尝试

    @messages + @images 
    

    你应该有你的组合数组。

    编辑#2:如果我自己写这个,我可能会像这样处理视图:

    在顶层,只需将您的提要集合传递给旨在呈现单个项目的部分:

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

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

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

    <%= display_item(item) %>
    

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

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

    【讨论】:

    • 感谢您的回复,我将如何将它们组合成控制器中的单个数组?关于局部的聪明想法,我忘记了。为什么你认为这是一个加载的问题?我是一个 Rails 菜鸟。
    • 乍一看,似乎需要很多细节才能得到问题的可靠答案,但希望这些想法是有用的。我用如何将数组附加在一起更新了答案。
    • 嘿Pete,很抱歉我问了这么多问题,但除了助手之外,我已经准备好了所有代码。我将如何定义 item.is_a?信息?再次感谢。
    • 我是否也将其在视图中设置为: "message", :locals => { :messages => @messages }%> "image", :locals => { :images => @images }%>
    • is_a?是Ruby内置的方法,所以不需要自己定义。
    猜你喜欢
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多