【问题标题】:Are there any model analytics gems?是否有任何模型分析宝石?
【发布时间】:2012-06-28 18:22:49
【问题描述】:

我正在努力让客户查看每天、每周、每月、一段时间内的分析,按小时、天或月等分组...所有这些都基于created_at 属性。

是否有任何宝石已经做到了这一点?比如:

Posts.analytics(:by => :day, :period => :this_week, :column => :created_at)

会返回:

{
'2012-06-19' => 14,
'2012-06-20' => 0, // Empty rows padding support*
'2012-06-21' => 3
}

我正在尝试从头开始,但如果已经有宝石可以完成这项工作,这似乎是很多不必要的工作。

更新

我尝试制作一个分析模块,该模块包含在所有模型中以便于生成分析,但它确实不可靠,有时我得到的天数超出了我的需要,而且真的很混乱,任何人都可以合作并重写/改进这个:

# Usage:
# include Analytics::Timeline
# Model.timeline(:period => :last_24_hours, :time_by => :hour)

module Analytics
  module Timeline
    def self.included(base)
      base.class_eval {

        def self.timeline(*filters)
          filters = filters[0]
          period  = filters[:period] || :this_week
          time_by = filters[:time_by] || :days
          date_column = filters[:date_column] || :created_at

          # Named periods conventions
          period_range = case period
            when :last_12_hours
              [Time.now-12.hours, Time.now]
            when :last_24_hours
              [Time.now-24.hours, Time.now]
            when :last_7_days
              [Time.now-7.days, Time.now]
            when :last_30_days
              [Time.now-30.days, Time.now]
            when :this_week
              [Time.now.beginning_of_week, Time.now.end_of_week]
            when :past_week
              [(Time.now - 1.week).beginning_of_week, (Time.now - 1.week).end_of_week]
            when :this_month
              [Time.now.beginning_of_month, Time.now.end_of_month]
            when :past_month
              [(Time.now-1.month).beginning_of_month, (Time.now - 1.month).end_of_month]
            when :this_year
              [Time.now.beginning_of_year, Time.now.end_of_year]
            end
          period_range = period if period.kind_of?(Array)
          period_range = [period, Time.now] if period.is_a?(String)

          # determine the SQL group method
          group_column = case time_by
            when :months
              time_suffix = "-01 00:00:00"
              records = where("#{table_name}.#{date_column} > ? AND #{table_name}.#{date_column} <= ?", period_range[0].to_date, period_range[1].to_date)
              "DATE_FORMAT(#{table_name}.#{date_column.to_s}, '%Y-%m')"
            when :days
              time_suffix = " 00:00:00"
              records = where("#{table_name}.#{date_column} > ? AND #{table_name}.#{date_column} <= ?", period_range[0].to_date, period_range[1].to_date)
              "DATE(#{table_name}.#{date_column.to_s})"
            when :hours
              time_suffix = ":00:00"
              records = where("#{table_name}.#{date_column} > ? AND #{table_name}.#{date_column} <= ?", period_range[0], period_range[1])
              "DATE_FORMAT(#{table_name}.#{date_column.to_s}, '%Y-%m-%d %H')"
            when :minutes
              time_suffix = ":00"
              records = where("#{table_name}.#{date_column} > ? AND #{table_name}.#{date_column} <= ?", period_range[0], period_range[1])
              "DATE_FORMAT(#{table_name}.#{date_column.to_s}, '%Y-%m-%d %H:%M')"
            end

          # Get counts per cycle
          records = records.group(group_column).select("*, count(*) AS series_count, #{group_column} AS series_time")
          series = {}

          # Generate placeholder series
          time_table = { :days => 60*60*24, :hours => 60*60, :minutes => 60, :seconds => 0 }

          if time_by == :months
            ticks = 12 * (period_range[1].year - period_range[0].year) + (period_range[1].month + 1) - period_range[0].month
          else
            ticks = (period_range[1] - period_range[0] + 1) / time_table[time_by]
          end

          ticks.to_i.times do |i|
            time = period_range[1]-i.send(time_by)
            time = case time_by
            when :minutes
              time.change(:sec => 0)
            when :hours
              time.change(:min => 0)
            when :days
              time.change(:hour => 0)
            when :months
              time.change(:day => 1, :hour => 0)
            end

            series[time.to_s(:db)] = 0
          end

          # Merge real counts with placeholder series
          to_merge = {}
          records.each do |r|
            to_merge[r.series_time.to_s+time_suffix] = r.series_count
          end

          series.merge!(to_merge)
        end

      }
    end
  end
end

【问题讨论】:

  • 冒着说出您已经知道或由于某种原因不适用的明显内容的风险,我只想指出,使用操作数据库(大量原子记录 CRUD 操作)进行分析和报告(大量大读取、索引/表扫描)会很快导致操作和分析性能出现问题。至少对我来说,这解释了为什么没有多少强大的解决方案可以嵌入到您的应用程序中——通常不建议将其作为一种架构方法。
  • 同意史蒂夫的意见,我只会手写查询:)

标签: ruby-on-rails gem


【解决方案1】:

ActiveRecord statistics gem 似乎对你很有用。

如果统计 gem 没有帮助,admin_data gem 内置了一些分析功能。查看the demo。使用整个管理系统可能有点矫枉过正,但您至少可以尝试浏览源代码以模仿分析功能。

【讨论】:

  • statistics 通过查看 github 页面似乎有点古老且无人维护
  • admin_data 现在也老了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 2016-05-18
  • 2015-12-23
  • 2012-01-25
相关资源
最近更新 更多