我有一些文章的销售表
id | user_id | article_id | status
1 | 1 | 1 | 0
2 | 1 | 2 | 0
3 | 2 | 2 | 0
4 | 1 | 1 | 1
5 | 2 | 2 | 1
status = 0
未经证实且status = 1
已确认
逻辑如下:用户点击按钮购买文章然后,记录以未确认状态保存在表格中。确认付款后,另一条记录将保存在表格中,状态为已确认。两个记录都保存在表中,以保持整个事务的时间表。 id
字段确定给定事务中最旧的记录。
在我的申请中,我想获得 5个最畅销文章的列表,这里是我到目前为止的表现:
# In articles_helper.rb
def get_articles_sold
# Fetch all Articles that are present in the Sales table
sales = Article.where(id: Sale.select(:article_id).map(&:article_id))
sold = []
sales.each do |s|
s.status.group_by(&:status).each do |status, sale|
if status.to_sym == :confirmed
sold << {article: s, sold: sale.count}
end
end
end
# Returns the sold array
sold
end
# In the Article model there's this Virtual Attribute 'status'
# It returns me the last status from a given transaction
def status
sales = Sale.where(article_id: self.id).order(id: :desc)
statuses = []
sales.group_by(&:user_id).each do |user, sale|
statuses << sale.first
end
statuses
end
#In my application
@most_sold_articles = get_articles_sold.sort_by{|v| v[:sold]}.reverse
它给我回复:
@most_sold_articles = [
{article: #<some_article_entity>, sold: 4},
{article: #<some_article_entity>, sold: 2},
{article: #<some_article_entity>, sold: 1},
]
这段代码实际上可以运行并给我我想要的东西,但我认为它是Ruby应用程序的很多代码。是否有任何优雅或更简单的方法来获得相同的结果?
答案 0 :(得分:3)
我认为应该这样做
@articles = Article
.joins(:sales)
.select("articles.*, count(sales.article_id) as sold")
.group('articles.id').order('sold DESC').limit(5)
如果您想要与答案中的格式相同
@most_sold_articles = @articles.map{|a| {article: a, sold: a.sold}}
#=> [
#=> {article: #<some_article_entity>, sold: 100},
#=> {article: #<some_article_entity>, sold: 80},
#=> {article: #<some_article_entity>, sold: 75},
#=> {article: #<some_article_entity>, sold: 66},
#=> {article: #<some_article_entity>, sold: 30}
#=> ]