0

我正在为我的 Rails 应用程序制作一个非常基本的分析功能。我想提供统计数据,告诉用户有多少访问者查看了他们的个人资料,然后还根据每个访问者拥有的特定角色(我在我的应用程序中使用“rolify”)对这些数据进行细分。

在用户控制器的显示动作中,我这样做

@profileviews = Profileview.where(:user_id => @user.id)
@profileviewsbysomerole = Profileview.where({:user_id => @user.id, :viewer_role => 'someRole'})
@profileviewsbysomeotherrole = Profileview.where({:user_id => @user.id, :viewer_role => 'someOtherRole'})

然后在表演动作中,我会做

Your profile has been viewed <%= @profileviews.size %> times.
Your profile has been viewed by users with a particular role <%= @profileviewsbysomerole.size %> times.
Your profile has been viewed by users with some other role <%= @profileviewsbysomeotherrole.size %> times.

有没有办法在不进行三个单独查询的情况下完成我想要做的事情,或者这是获得这些统计数据的最佳方式(就不降低性能而言)。

4

3 回答 3

1

就性能而言,我认为还可以。另一种选择是查询所有对象,然后在内存中过滤,但我认为这不是一个好主意。最好让数据库做它最擅长的事情。

想到的一件事——您可以使用单个查询和group_by以避免进行第二次和第三次调用,但如果您希望获得一些聚合数据,这很重要。

在编码风格方面,您可以为不同的查询定义范围并从视图中使用它们,但这可能是一种矫枉过正。

于 2013-05-01T20:58:37.633 回答
1

如果您发现自己经常将这些东西一起使用,那么将它们捆绑在一起可能会很好,如下所示:

# in user model
def profile_view_hash(*roles)
  views = { 'all' => Profileview.where(:user_id => id).all }
  roles.each do |role|
    views.merge!({
      role => Profileview.where(:user_id => id, :viewer_role => role).all
    })
  end
  views
end

这应该允许您像这样使用它:

# in controller
@profile_views = @user.profile_view_hash('someRole','someOtherRole')

# in view
<%= @profile_views['all'] %>
<%= @profile_views['someRole'] %>
<%= @profile_views['someOtherRole'] %>

顺便说一句,在您的示例中,您只显示了.size 的输出。如果这就是你所需要的,你应该使用count而不是all

于 2013-05-01T21:30:27.423 回答
1

我会将它们全部排除在控制器之外,并制作如下视图:

Your profile has been viewed <%= @user.profileviews.size %> times.
Your profile has been viewed by users with a particular role <%= @user.profileviews.select { |profile_view| profile_view.viewer_role == 'someRole' }.size %> times.
Your profile has been viewed by users with some other role <%= @user.profileviews.select { |profile_view| profile_view.viewer_role == 'someOtherRole' }.size %> times.

通过将此逻辑移至Profileview,您可以更进一步,例如:

def views_for_role( role )
  select { |profile_view| profile_view.viewer_role == role }.size
end

并将其委托给User,也许像:

delegate :views_for_role, :to => :profileview

这将使您的视图如下所示:

Your profile has been viewed <%= @user.profileviews.size %> times.
Your profile has been viewed by users with a particular role <%= @user.views_for_role 'someRole' %> times.
Your profile has been viewed by users with some other role <%= @user.views_for_role 'someOtherRole' %> times.
于 2013-05-02T02:37:24.947 回答