使用Rails 4,在控制器中我想为实例变量添加一个属性。
抱歉这个糟糕的例子,我试图保持简单。
E.g。在控制器中,我通过查找名为John的一些用户来创建一个新的实例变量。现在,在我的控制器中,我想总结所有名为John的用户的年龄,将这个总和年龄放回实例变量中,以便视图可用。
用户模型具有'id','name'和'age'属性。
@foo_users = Users.where(name: 'John')
@foo_users.each do |foo|
@foo_users.age_sum = Users.where(name: 'John').sum(:age) <-- this does not work
end
我没有必要将这个总计年龄保存回数据库,因为我只会在一个视图中使用它。我希望能够显示所有用户:
<% @foo_users.each do |user| %>
User name: <%= user.name =>
Sum of ages: <%= user.age_sum %>
<% end %>
更新:我可能过度简化了我的示例。这是一个更贴近现实的例子。
一家公司拥有酒店。酒店有房间。管理软件通过API向公司每日提供Hotel_Statistics。由于缺乏更好的词汇,这些Hotel_Statistics包含hotel_id,每日登记入住,每日退房。在我正在处理的公司的后台Rails应用程序中,在显示的页面上有一个酒店列表,其中包含最新的统计数据。一行看起来像:
Hotel Id: 123
Daily check-ins: 50
Daily check-outs: 48
Hotel Id: 124
Daily check-ins: 35
Daily check-outs: 37
该公司还希望显示最近30天签到(出局,网上办理登机手续)的运行总额。 为了实现这一点,在我的控制器中,我找到了最近日期(通常是昨天)的Hotel_Statics。
latest_stat = HotelStatistic.order('date DESC, hotel_id DESC').first
@latest_date = latest_stat.date
@recent_stats = HotelStatistic.where(date: @latest_date).order('hotel.id ASC').all
我在视图中显示@recent_stats的详细信息。
现在,我想在我的视图中显示每个酒店@ last_stats.check_ins的最近30天的总和。我的想法是总结一下给定酒店的最后30天check_ins统计数据:
@recent_stats.each do |stat|
@last_30_days_check_ins = HotelStatistic.where(hotel_id: stat.hotel_id).where("date >= ?", Date.today - 30).sum(:check_ins)
end
数学有效,但我需要一种方法来访问每家酒店的30天总和变量。我希望通过将酒店30天的总和添加到@recent_stats实例变量来使视图变得简单,所以在我看来我可以这样做:
<% @recent_stats.each do |statistic| %>
Hotel Id: <%= statistic.hotel_id %>
Daily check-ins: <%= statistic.check_ins %>
Last 30 days check-ins: <%= statistic.last_30_days_check_ins %>
<% end %>
这个更现实的例子是否会改变您建议的答案中的任何内容?感谢
答案 0 :(得分:0)
使用select
可以解决您的问题:
@users = User.select("*, SUM(age) as age_sum").where(name: 'John')
现在User
数组中的每个@users
都有一个age_sum
属性。这并非100%理想,因为每个实例的属性值都相同,但它将与您设置视图的方式一致。
修改强> 可以手动动态定义实例上的方法:
@foo_users.each do |foo|
def foo.age_sum; Users.where(name: 'John').sum(:age); end;
end
然而,虽然这是可能的,但它必须是一个非常好的用例来证明这可能产生的负面影响(例如代码的可读性,有效性和可维护性)。可能有更好的OO方法来解决同样的问题
答案 1 :(得分:0)
@foo_users
的类型为ActiveRecord::Relation
。尝试将age_sum
作为新属性添加到ActiveRecord::Relation
对象没有意义,因为语义age_sum
不是ActiveRecord::Relation
个对象的属性。最好将年龄总和存储在新的实例变量中,例如@user_age_sum
。
<强>更新强> 请尝试以下
class HotelStatistic < ActiveRecord::Base
belongs_to :hotel
end
class Hotel < ActiveRecord::Base
has_many :hotel_statistics
def last_30_days_check_ins
self.hotel_statistics.where("date >= ?", 30.days.ago).sum(:check_ins)
end
end
保留用于在控制器中构建@recent_stats
的现有代码
在视图中
<% @recent_stats.each do |statistic| %>
Hotel Id: <%= statistic.hotel_id %>
Daily check-ins: <%= statistic.check_ins %>
Last 30 days check-ins: <%= statistic.hotel.last_30_days_check_ins %>
<% end %>