Ruby on rails 合并三个活动记录阵列

Ruby on rails 合并三个活动记录阵列,ruby-on-rails,heroku,activerecord,Ruby On Rails,Heroku,Activerecord,我正在尝试在Rails 5应用程序中合并三个活动记录阵列,以便在我的主页上有一个很好的作业、论坛线程和博客集合 我有以下代码: application\u controller.rb def home @blogs = Blog.limit(6) @jobs = Job.where(approved: true).limit(6) @forum_threads = ForumThread.includes(:forum_posts).limit(6) @everything =

我正在尝试在Rails 5应用程序中合并三个活动记录阵列,以便在我的主页上有一个很好的作业、论坛线程和博客集合

我有以下代码:

application\u controller.rb

def home
  @blogs = Blog.limit(6)
  @jobs = Job.where(approved: true).limit(6)
  @forum_threads = ForumThread.includes(:forum_posts).limit(6)
  @everything = @blogs + @jobs + @forum_threads
end
class Blog < ActiveRecord::Base
  default_scope { order created_at: :desc }
  ...
end
module Timestamped
  extend ActiveSupport::Concern

  included do
    scope :most_recent,  -> { order created_at: :desc }
    scope :least_recent, -> { order created_at: :asc }
    scope :most_fresh,   -> { order updated_at: :desc }
    scope :least_fresh,  -> { order updated_at: :asc }
  end
end

class Blog < ActiveRecord::Base
  include Timestamped
  ...
end
class Array
  def most_recent
    sort { |a, b| b.created_at <=> a.created_at }
  end
end
require 'array_extensions'
home.html.erb

<% @everything.sort_by(&:created_at).reverse.each do |item| %>
    <% if item.is_a?(Job) %>
      <%= render partial: "application/partials/home_job", locals: {item: item} %>
    <% elsif item.is_a?(ForumThread) %>
      <%= render partial: "application/partials/home_forum", locals: {item: item} %>
    <% elsif item.is_a?(Blog) %>
      <%= render partial: "application/partials/home_blog", locals: {item: item} %>
    <% end %>
<% end %>

我遇到的问题是,这段代码没有按日期顺序显示由创建的记录,而是从一个看似随机的日期开始随机收集作业、论坛线程和博客

例如,如果我添加一个新作业,它不会出现在
/home
页面上显示的集合中。但是,如果我从数据库中删除所有记录并开始添加新记录,那么代码工作正常,并按照我期望的行为以正确的顺序显示帖子

我无法将此代码实时推送到Heroku,因为我无法删除生产中已经存在的所有记录。这就好像有某种缓存需要清除。有人知道发生了什么事吗

 @blogs = Blog.order(created_at: :desc).limit(6)
等等。

您可以这样做:

def home
  @collections=[]
  @collections << Blog.limit(6)
  @collections << Job.where(approved: true).limit(6)
  @collections << ForumThread.includes(:forum_posts).limit(6)
end

<% @collections.flatten.sort_by(&:created_at).reverse.each do |item| %>

....iteration here ....

<% end %>
def home
@集合=[]

@集合如果我正确理解了您的问题,您希望在按日期合并数组后对其进行排序。我会这样做:

@everything = @everything.sort {|x| x.created_at }

希望有帮助。

问题1:从数据库中获取正确的记录

选项A:如果您总是按照创建的\u at值对每个模型进行排序(这是一个共同的愿望),请为每个模型添加一个默认的\u范围(下面是Rails 4+版本)。控制器中的限制调用将自动利用默认范围

app/models/blog.rb

def home
  @blogs = Blog.limit(6)
  @jobs = Job.where(approved: true).limit(6)
  @forum_threads = ForumThread.includes(:forum_posts).limit(6)
  @everything = @blogs + @jobs + @forum_threads
end
class Blog < ActiveRecord::Base
  default_scope { order created_at: :desc }
  ...
end
module Timestamped
  extend ActiveSupport::Concern

  included do
    scope :most_recent,  -> { order created_at: :desc }
    scope :least_recent, -> { order created_at: :asc }
    scope :most_fresh,   -> { order updated_at: :desc }
    scope :least_fresh,  -> { order updated_at: :asc }
  end
end

class Blog < ActiveRecord::Base
  include Timestamped
  ...
end
class Array
  def most_recent
    sort { |a, b| b.created_at <=> a.created_at }
  end
end
require 'array_extensions'
问题2:对数组排序

即使是这样一个简单的例子,我还是建议添加一个数组扩展,该扩展与timestamp.rb为ActiveRecord::Relations定义的最新方法相匹配

lib/array\u extensions.rb

def home
  @blogs = Blog.limit(6)
  @jobs = Job.where(approved: true).limit(6)
  @forum_threads = ForumThread.includes(:forum_posts).limit(6)
  @everything = @blogs + @jobs + @forum_threads
end
class Blog < ActiveRecord::Base
  default_scope { order created_at: :desc }
  ...
end
module Timestamped
  extend ActiveSupport::Concern

  included do
    scope :most_recent,  -> { order created_at: :desc }
    scope :least_recent, -> { order created_at: :asc }
    scope :most_fresh,   -> { order updated_at: :desc }
    scope :least_fresh,  -> { order updated_at: :asc }
  end
end

class Blog < ActiveRecord::Base
  include Timestamped
  ...
end
class Array
  def most_recent
    sort { |a, b| b.created_at <=> a.created_at }
  end
end
require 'array_extensions'
问题3:保持控制器清洁。

通常,每个控制器操作只应设置一个实例变量,在这种情况下,看起来您甚至没有在视图中使用@blogs、@jobs和@forum_threads变量。Vivek的答案解决了这个问题,尽管我会在控制器中执行展平和排序逻辑:

def home
  @posts = Blog.most_recent.limit(6) + Job.approved.most_recent.limit(6) + ForumThread.most_recent.includes(:forum_posts).limit(6)
  @posts = @posts.most_recent
end
问题4:最小化视图中的if/then逻辑

与此相反:

<% @everything.sort_by(&:created_at).reverse.each do |item| %>
  <% if item.is_a?(Job) %>
    <%= render partial: "application/partials/home_job", locals: {item: item} %>
  <% elsif item.is_a?(ForumThread) %>
    <%= render partial: "application/partials/home_forum", locals: {item: item} %>
  <% elsif item.is_a?(Blog) %>
    <%= render partial: "application/partials/home_blog", locals: {item: item} %>
  <% end %>
<% end %>

这样做:

<% @everything.sort_by(&:created_at).reverse.each do |item| %>
  <%= render "application/partials/home_#{item.class.name.underscore}", item: item %>
<% end %>


并确保您的部分名称正确

原则上良好。我建议
Blog.order(创建于::desc.).limit(6)
否则,在订单之前提供限制,最新的可能不包括在内。如果我这样做,那么三个不同的集合将组合在一起。所以所有的博客帖子都挨着一个,工作也挨着一个。。。我想让它们混合在一起,按照created_byNo排序,你仍然可以做@everything,然后按
排序@KcUS_unico answer只会确保您首先获得正确的记录。需要
(在::desc创建)
(“在desc创建”)
,否则您只能获得最旧的记录。@SteveTurczyn=>谢谢。现在我将使用选项A,但我只是重构了代码以清理控制器并避免视图中的if/else语句。我甚至不知道你能做
“application/partials/home#{item.class.name.underline}”
所以谢谢你教我一些新东西,很高兴它很有用!