我试图在Rails 5应用程序中合并三个Active Record数组,以便在我的主页上有一个很好的作业集,论坛帖子和博客。
我有以下代码:
application_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
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 %>
我遇到的问题是,此代码不会按created_by
按日期顺序显示记录,相反,我有一个相当随机的作业集,论坛帖子和博客看似随意的约会。
如果我添加新作业,它就不会出现在/home
页面上显示的集合中。但是,如果我从数据库中删除所有记录并开始添加新记录,那么代码工作正常,并按照我期望的行为以正确的顺序显示帖子。
我无法将此代码推送到Heroku,因为我无法删除生产中已存在的所有记录。它几乎就像需要清理某种缓存一样。有谁知道发生了什么?
答案 0 :(得分:2)
function dealPoints(c){
var nums = Array(6*c).fill().map((_,i) => i+1);
return nums.reduce(function(r,n,i){
var j = i%c;
j === 0 && (r.switch = !r.switch);
r.switch ? r[j].push(n) : r[c-j-1].push(n);
return r;
}, Array(c).fill().map(_ => []));
}
var players = 3,
result = dealPoints(players);
console.log(result);
等
答案 1 :(得分:1)
问题1:从数据库中获取正确的记录
选项A :如果您将始终按created_at值(常见的愿望)对每个模型进行排序,请为每个模型添加default_scope(下面的Rails 4+版本)。控制器中的限制调用将自动利用默认范围。
app/models/blog.rb
class Blog < ActiveRecord::Base
default_scope { order created_at: :desc }
...
end
选项B :如果您仅在某些情况下执行此操作,但是您针对多个模型执行此操作,我希望将其提取到Timestamped模块中(如下所示)。从数据库中提取记录时,您需要在控制器中使用most_recent方法,以确保获得最新的记录。
app/models/concerns/timestamped.rb
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
问题2:对数组进行排序
即使有这样一个简单的情况,我建议添加一个数组扩展,该扩展与timestamped.rb为ActiveRecord :: Relations定义的most_recent方法相匹配。
lib/array_extensions.rb
class Array
def most_recent
sort { |a, b| b.created_at <=> a.created_at }
end
end
然后要求使用初始化程序进行扩展:
config/initializers/extensions.rb
require 'array_extensions'
问题3:保持控制器清洁。
通常每个控制器操作应该只设置一个实例变量,在这种情况下,看起来你甚至没有在视图中使用@ blogs,@ job和@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 %>
确保您的部分名称正确
答案 2 :(得分:0)
你可以这样做:
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 %>
答案 3 :(得分:0)
如果我正确理解了您的问题,您希望在按日期合并后对数组进行排序。我会那样做:
@everything = @everything.sort {|x| x.created_at }
希望有所帮助。