我试图将对象融合成一个流.
我创建了一个名为Newsfeed的新模型和控制器.我有它所以新闻源has_many:消息和has_many:图像和图像和消息belongs_to:newsfeed.我正在设置控制器,我有:
def index
@messages = Messages.all
@images = Images.all
@feed = ?
end
Run Code Online (Sandbox Code Playgroud)
我如何将它们融合在一起,以便它们可以从两者中拉出来并按每个需要单独形成时按时间顺序排列?
非常感谢任何帮助,谢谢.
Mik*_*ike 18
你可以做一些事情:
控制器:
def index
messages = Messages.all
images = Images.all
@feed = (messages + images).order_by(&:created_at)
end
Run Code Online (Sandbox Code Playgroud)
查看index.html.erb:
<%= render @feed %>
Run Code Online (Sandbox Code Playgroud)
查看_feed.html.erb:
<% if feed.is_a? Message %>
<%= render "message", :locals => {:message => feed}%>
<% else %>
<%= render "image", :locals => {:image => feed}%>
<% end %>
Run Code Online (Sandbox Code Playgroud)
并添加2个部分_message.html.erb和_image.html.erb
我确信这可以从它的贫民窟多态性中得到简化,但它对我有用,而且我与"我如何结合所有这些模型结果?"进行了相同的斗争?
我和你一样使用一个单独的模型和一个观察者:
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
Run Code Online (Sandbox Code Playgroud)
然后在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
Run Code Online (Sandbox Code Playgroud)
然后只需拉动它们,然后在您的视图中显示.
#Controller
def index
@feed = Newsfeed.get_items
end
Run Code Online (Sandbox Code Playgroud)
展望未来,我可能会开始将更多内容打包到流跟踪模型中,以便在其他表上保存命中,但希望您能得到这个想法.
这感觉像是一个有点沉重的问题,虽然我没有时间全面深入研究它,但这里有一些初步的想法:
您可以将要显示的两种类型的项目组合到一个数组中,然后根据两者之间应该通用的字段对该数组进行排序(想到了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
Run Code Online (Sandbox Code Playgroud)
希望这对一些人有帮助!
编辑:要组合数组,您可以简单地使用“+”运算符将它们附加在一起,因为 Ruby 中的数组不需要包含单个对象类型。
您的 Messages.all 和 Images.all 调用为您提供对象数组,所以只需尝试
@messages + @images
Run Code Online (Sandbox Code Playgroud)
你应该有你的组合数组。
编辑#2:如果我自己写这个,我可能会像这样处理视图:
在顶层,只需将您的提要集合传递到旨在呈现单个项目的部分:
render :partial => "item", :collection => @feed
Run Code Online (Sandbox Code Playgroud)
这将为 @feed 中的每个项目呈现“_item.html.erb”部分。此外,它每次都会为该部分提供一个名为“item”的局部变量,这是该特定迭代的 @feed 中的项目。
现在,我可能会让 '_item' 部分非常简单,如下所示:
<%= display_item(item) %>
Run Code Online (Sandbox Code Playgroud)
其中 display_item 是视图外部的辅助方法,并通过“is_a?”实现。输入上面的逻辑来为该项目选择正确的显示格式。
我之所以会这样分解它,是因为它利用了一些不错的 Rails 功能(将集合传递给部分组件,而不是自己循环遍历集合),然后将逻辑拉出到助手中(甚至是模型,如果有意义的话) to) 很有用,因为它简化了您的视图。尽可能将逻辑保持在视图之外通常是一个很好的做法,因为这样的逻辑可能很难测试,并且您的视图将变得很难阅读。