我有一个书籍视图,客户可以访问他们最新的产品。我正在尝试展示当前的产品和过期的产品。所有这一切都很好,除了重复的订单 - 我想消除欺骗。
e.g。如果当前图书标题与过期标题具有相同的标题,则不显示过期标题,如果过期订单与过期标题具有相同标题,则仅显示一个标题。
这是我的图书索引。
<% if current_user_subscribed? %>
<% @current_user.orders.map do |order| %>
<% order.product.books.map do |book| %>
<% if order.created_at + order.expires.minutes > Time.now %>
<%= link_to book.title, book %>
# show book.title without dupes
<% elsif order.product_id != order.product_id %>
<%= link_to book.title, book %>
<% end %>
<% end %>
<% end %>
答案 0 :(得分:1)
听起来像模特关注的问题,而不是视角问题。
# Model
class Book < ActiveRecord::Base
# Class methods are allowed to be chained on ActiveRecord::Relation returned by order.books
# @return [Array<Book>]
def self.without_dups
group_by(&:title).map do |title, books|
# Here I assume you simply want one book per title, with preference for the non-expired ones
books.sort_by {|book| book.is_expired ? 0 : 1}.first
end
end
end
# Controller
class BooksController < ApplicationController
def index
# includes is used to avoid N+1 queries
@orders = current_user.orders.includes(:books)
end
end
# View
<% @orders.each do |order| %>
<% order.books.without_dups.each do |book| %>
...
<% end %>
<% end %>
您的原始视图代码包含许多逻辑。它通过直接在@current_user上调用方法来自行决定呈现什么。如果视图侧重于如何呈现,同时保留要呈现给控制器的内容,则效果会更好。这就是我的控制器设置@orders
并从那里开始视图的原因。此外,调用#map
是不必要的。您不依赖于返回值。它没有害处,但#each
在这种情况下更自然。