| Setting up specs to run on mysql - reportable - Fork of reportable required by … | |
| Log | |
| Files | |
| Refs | |
| README | |
| --- | |
| commit 400b8c6b4167aa2e93683aa7ff34d0758c5292b5 | |
| parent 5d9e03aa1f738e273aeca4d0ba7dca3107ec3657 | |
| Author: Martin Kavalar <[email protected]> | |
| Date: Mon, 12 May 2008 14:46:47 +0200 | |
| Setting up specs to run on mysql | |
| Diffstat: | |
| A History.txt | 0 | |
| A Manifest.txt | 0 | |
| A README.txt | 47 +++++++++++++++++++++++++++++… | |
| M lib/reports_as_sparkline/report.rb | 281 ++++++++++++++++-------------… | |
| A lib/reports_as_sparkline/report_ca… | 0 | |
| A spec/boot.rb | 23 +++++++++++++++++++++++ | |
| M spec/db/database.yml | 4 ++-- | |
| M spec/db/schema.rb | 11 +++++++++++ | |
| M spec/reports_as_sparkline_spec.rb | 4 ++-- | |
| M spec/spec_helper.rb | 48 +++++++++++++++++++++++++++++… | |
| 10 files changed, 271 insertions(+), 147 deletions(-) | |
| --- | |
| diff --git a/History.txt b/History.txt | |
| diff --git a/Manifest.txt b/Manifest.txt | |
| diff --git a/README.txt b/README.txt | |
| @@ -0,0 +1,46 @@ | |
| += reports_as_sparkline | |
| + | |
| +* http://github.com/mk/reports_as_sparkline | |
| + | |
| +== DESCRIPTION: | |
| + | |
| +FIX (describe your package) | |
| + | |
| +== FEATURES/PROBLEMS: | |
| + | |
| +* FIX (list of features or problems) | |
| + | |
| +== SYNOPSIS: | |
| + | |
| + FIX (code sample of usage) | |
| + | |
| +== REQUIREMENTS: | |
| + | |
| +* edge rails | |
| + | |
| +== INSTALL: | |
| + | |
| +* sudo gem install reports_as_sparkline | |
| + | |
| +== LICENSE: | |
| + | |
| +Copyright (c) 2008 Martin Kavalar | |
| + | |
| +Permission is hereby granted, free of charge, to any person obtaining | |
| +a copy of this software and associated documentation files (the | |
| +'Software'), to deal in the Software without restriction, including | |
| +without limitation the rights to use, copy, modify, merge, publish, | |
| +distribute, sublicense, and/or sell copies of the Software, and to | |
| +permit persons to whom the Software is furnished to do so, subject to | |
| +the following conditions: | |
| + | |
| +The above copyright notice and this permission notice shall be | |
| +included in all copies or substantial portions of the Software. | |
| + | |
| +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | |
| +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| +\ No newline at end of file | |
| diff --git a/lib/reports_as_sparkline/report.rb b/lib/reports_as_sparkline/repo… | |
| @@ -1,155 +1,156 @@ | |
| module ReportsAsSparkline #:nodoc: | |
| - def self.included(base) | |
| - base.extend ClassMethods | |
| - end | |
| - | |
| - class InvalidGroupExpception < Exception | |
| - end | |
| - | |
| - class InvalidOperationExpception < Exception | |
| - end | |
| - | |
| - class ReportingGroup | |
| - @@ranges = [:month, :week, :day, :hour] | |
| - | |
| - attr_reader :group | |
| - | |
| - def initialize(range) | |
| - raise Kvlr::ReportsAsSparkline::InvalidGroupExpception unless @@ranges… | |
| - @group = range.to_sym | |
| - end | |
| - | |
| - def group_sql(attribute) | |
| - attribute = attribute.to_s | |
| - raise "No date_column given" if attribute.blank? | |
| - case @group | |
| - when :day | |
| - group_by = "DATE(#{attribute})" | |
| - when :week | |
| - group_by = "YEARWEEK(#{attribute})" | |
| - when :month | |
| - group_by = "YEAR(#{attribute}) * 100 + MONTH(#{attribute})" | |
| - when :hour | |
| - group_by = "DATE(#{attribute}) + HOUR(#{attribute})" | |
| - end | |
| - group_by | |
| - end | |
| - | |
| - def latest_datetime | |
| - case @group | |
| - | |
| - when :day, :week, :month | |
| - return 1.send(@group).ago.to_date.to_datetime | |
| - when :hour | |
| - return 1.day.ago.to_date.to_datetime | |
| - end | |
| - end | |
| - | |
| - def self.default | |
| - :day | |
| - end | |
| + def self.included(base) | |
| + base.extend ClassMethods | |
| + end | |
| + | |
| + class ReportCache < ActiveRecord::Base | |
| + end | |
| + | |
| + class InvalidGroupExpception < Exception | |
| + end | |
| + | |
| + class InvalidOperationExpception < Exception | |
| + end | |
| + | |
| + class ReportingGroup | |
| + @@ranges = [:month, :week, :day, :hour] | |
| + | |
| + attr_reader :group | |
| + | |
| + def initialize(range) | |
| + raise ReportsAsSparkline::InvalidGroupExpception unless @@ranges.include… | |
| + @group = range.to_sym | |
| end | |
| - | |
| - class ReportingOperation | |
| - @@operations = [:count, :sum] | |
| - | |
| - attr_reader :operation | |
| - | |
| - def initialize(op) | |
| - raise Kvlr::ReportsAsSparkline::InvalidOperationExpception unless @@op… | |
| - @operation = op.to_sym | |
| - end | |
| - | |
| - def self.default | |
| - :count | |
| + | |
| + def group_sql(attribute) | |
| + attribute = attribute.to_s | |
| + raise "No date_column given" if attribute.blank? | |
| + case @group | |
| + when :day | |
| + group_by = "DATE(#{attribute})" | |
| + when :week | |
| + group_by = "YEARWEEK(#{attribute})" | |
| + when :month | |
| + group_by = "YEAR(#{attribute}) * 100 + MONTH(#{attribute})" | |
| + when :hour | |
| + group_by = "DATE(#{attribute}) + HOUR(#{attribute})" | |
| end | |
| + group_by | |
| end | |
| - | |
| - class Report | |
| - | |
| - @@default_statement_options = {:limit => 100, :operation => ReportingOpe… | |
| - attr_reader :name, :operation, :date_column, :value_column, :graph_optio… | |
| - | |
| - def initialize(name, options) | |
| - @name = name.to_sym | |
| - @value_column = (options[:value_column] || @name).to_sym | |
| - @statement_options = @@default_statement_options.merge options | |
| - | |
| - @reporting_group = ReportingGroup.new(@statement_options[:group]) | |
| - @reporting_operation = ReportingOperation.new(@statement_options[:oper… | |
| - end | |
| + def latest_datetime | |
| + case @group | |
| - def report(klass, options) | |
| - statement_options = options.merge(@statement_options) | |
| - reporting_group = statement_options[:group] != @reporting_group.group … | |
| - reporting_operation = statement_options[:operation] != @reporting_oper… | |
| - | |
| - conditions = ["model_name = ? AND report_name = ? AND report_range = ?… | |
| - newest_report = ReportCache.find(:first, :select => "start, value", :c… | |
| - newest_value = reporting_group.latest_datetime | |
| - if newest_report.nil? or newest_report.start < newest_value | |
| - value_statement = nil | |
| - case reporting_operation.operation | |
| - when :sum | |
| - value_statement = "SUM(#{@value_column})" | |
| - when :count | |
| - value_statement = "COUNT(1)" | |
| - end | |
| - raise if value_statement.nil? | |
| - | |
| - where = ["#{reporting_group.group_sql(statement_options[:date_column… | |
| - where << "#{reporting_group.group_sql(statement_options[:date_column… | |
| - where = where.join(" AND ") | |
| - | |
| - query = "INSERT INTO #{ReportCache.table_name} (model_name, report_… | |
| - ( | |
| - SELECT \"#{klass.to_s}\", \"#{name}\", \"#{reporting_group.group… | |
| - #{reporting_group.group_sql(statement_options[:date_column])} … | |
| - #{value_statement} AS value | |
| - FROM #{klass.table_name} | |
| - WHERE #{where} | |
| - GROUP BY start | |
| - );" | |
| - ActiveRecord::Base.connection.execute query | |
| - end | |
| - data = ReportCache.find(:all, :select => "start, value", :conditions =… | |
| - data.collect! {|report| [report.start, report.value] } | |
| - data.reverse | |
| + when :day, :week, :month | |
| + return 1.send(@group).ago.to_date.to_datetime | |
| + when :hour | |
| + return 1.day.ago.to_date.to_datetime | |
| end | |
| - | |
| - # def generate_report(klass, options) | |
| - # | |
| - # | |
| - # case reporting_operation.operation | |
| - # when :sum | |
| - # return klass.sum @value_column, :group => @reporting_group.group_s… | |
| - # when :count | |
| - # return klass.count :group => @reporting_group.group_sql(@statement… | |
| - # end | |
| - # end | |
| end | |
| + | |
| + def self.default | |
| + :day | |
| + end | |
| + end | |
| + | |
| + class ReportingOperation | |
| + @@operations = [:count, :sum] | |
| + | |
| + attr_reader :operation | |
| + | |
| + def initialize(op) | |
| + raise ReportsAsSparkline::InvalidOperationExpception unless @@operations… | |
| + @operation = op.to_sym | |
| + end | |
| + | |
| + def self.default | |
| + :count | |
| + end | |
| + end | |
| + | |
| + | |
| + class Report | |
| + | |
| + @@default_statement_options = {:limit => 100, :operation => ReportingOpera… | |
| + attr_reader :name, :operation, :date_column, :value_column, :graph_options… | |
| + | |
| + def initialize(name, options) | |
| + @name = name.to_sym | |
| + @value_column = (options[:value_column] || @name).to_sym | |
| + @statement_options = @@default_statement_options.merge options | |
| + @reporting_group = ReportingGroup.new(@statement_options[:group]) | |
| + @reporting_operation = ReportingOperation.new(@statement_options[:operat… | |
| + end | |
| + | |
| + def report(klass, options) | |
| + statement_options = options.merge(@statement_options) | |
| + reporting_group = statement_options[:group] != @reporting_group.group ? … | |
| + reporting_operation = statement_options[:operation] != @reporting_operat… | |
| - class CumulateReport < Kvlr::ReportsAsSparkline::Report | |
| - | |
| - def report(klass, options) | |
| - CumulateReport.cumulate!(super(klass, options)) | |
| - end | |
| - | |
| - protected | |
| - def self.cumulate!(data) | |
| - last_item = 0 | |
| - data.collect{ |element| | |
| - last_item += element[1].to_i | |
| - [element[0], last_item] | |
| - } | |
| - end | |
| + conditions = ["model_name = ? AND report_name = ? AND report_range = ?",… | |
| + newest_report = ReportCache.find(:first, :select => "start, value", :con… | |
| + newest_value = reporting_group.latest_datetime | |
| + if newest_report.nil? or newest_report.start < newest_value | |
| + value_statement = nil | |
| + case reporting_operation.operation | |
| + when :sum | |
| + value_statement = "SUM(#{@value_column})" | |
| + when :count | |
| + value_statement = "COUNT(1)" | |
| + end | |
| + raise if value_statement.nil? | |
| + where = ["#{reporting_group.group_sql(statement_options[:date_column])… | |
| + where << "#{reporting_group.group_sql(statement_options[:date_column])… | |
| + where = where.join(" AND ") | |
| + | |
| + query = "INSERT INTO #{ReportCache.table_name} (model_name, report_na… | |
| + ( | |
| + SELECT \"#{klass.to_s}\", \"#{name}\", \"#{reporting_group.group.t… | |
| + #{reporting_group.group_sql(statement_options[:date_column])} AS… | |
| + #{value_statement} AS value | |
| + FROM #{klass.table_name} | |
| + WHERE #{where} | |
| + GROUP BY start | |
| + );" | |
| + ActiveRecord::Base.connection.execute query | |
| + end | |
| + data = ReportCache.find(:all, :select => "start, value", :conditions => … | |
| + data.collect! {|report| [report.start, report.value] } | |
| + data.reverse | |
| end | |
| - | |
| + | |
| + # def generate_report(klass, options) | |
| + # | |
| + # | |
| + # case reporting_operation.operation | |
| + # when :sum | |
| + # return klass.sum @value_column, :group => @reporting_group.group_sql… | |
| + # when :count | |
| + # return klass.count :group => @reporting_group.group_sql(@statement_o… | |
| + # end | |
| + # end | |
| end | |
| - | |
| + | |
| + | |
| + class CumulateReport < ReportsAsSparkline::Report | |
| + | |
| + def report(klass, options) | |
| + CumulateReport.cumulate!(super(klass, options)) | |
| + end | |
| + | |
| + protected | |
| + def self.cumulate!(data) | |
| + last_item = 0 | |
| + data.collect{ |element| | |
| + last_item += element[1].to_i | |
| + [element[0], last_item] | |
| + } | |
| + end | |
| + | |
| + end | |
| + | |
| module ClassMethods | |
| # | |
| # Examples: | |
| @@ -167,7 +168,7 @@ module ReportsAsSparkline #:nodoc: | |
| # report_as_sparkline :rake, :operation => :sum | |
| # end | |
| def report_as_sparkline(name, options = {}) | |
| - report = options[:cumulate] ? Kvlr::ReportsAsSparkline::CumulateReport.n… | |
| + report = options[:cumulate] ? ReportsAsSparkline::CumulateReport.new(opt… | |
| (class << self; self; end).instance_eval { | |
| define_method "#{name.to_s}_report".to_sym do |*args| | |
| raise ArgumentError if args.size > 1 | |
| diff --git a/lib/reports_as_sparkline/report_cache.rb b/lib/reports_as_sparklin… | |
| diff --git a/spec/boot.rb b/spec/boot.rb | |
| @@ -0,0 +1,23 @@ | |
| +plugin_root = File.join(File.dirname(__FILE__), '..') | |
| +version = ENV['RAILS_VERSION'] | |
| +version = nil if version and version == "" | |
| + | |
| +# first look for a symlink to a copy of the framework | |
| +if !version and framework_root = ["#{plugin_root}/rails", "#{plugin_root}/../.… | |
| + puts "found framework root: #{framework_root}" | |
| + # this allows for a plugin to be tested outside of an app and without Rails … | |
| + $:.unshift "#{framework_root}/activesupport/lib", "#{framework_root}/activer… | |
| +else | |
| + # simply use installed gems if available | |
| + puts "using Rails#{version ? ' ' + version : nil} gems" | |
| + require 'rubygems' | |
| + | |
| + if version | |
| + gem 'rails', version | |
| + else | |
| + gem 'actionpack' | |
| + gem 'activerecord' | |
| + end | |
| + require 'active_record' | |
| + require 'action_pack' | |
| +end | |
| diff --git a/spec/db/database.yml b/spec/db/database.yml | |
| @@ -5,7 +5,7 @@ sqlite3: | |
| mysql: | |
| adapter: mysql | |
| - username: rails | |
| - password: mislav | |
| + username: root | |
| + password: | |
| encoding: utf8 | |
| database: reports_as_sparkline_test | |
| diff --git a/spec/db/schema.rb b/spec/db/schema.rb | |
| @@ -3,4 +3,15 @@ ActiveRecord::Schema.define(:version => 1) do | |
| t.string :login, :string | |
| t.timestamps | |
| end | |
| + | |
| + create_table :report_caches, :force => true do |t| | |
| + t.string :model_name | |
| + t.string :report_name | |
| + t.string :report_range | |
| + t.float :value | |
| + t.datetime :start | |
| + | |
| + t.timestamps | |
| + end | |
| + add_index :report_caches, [:model_name, :report_name, :report_range, :start]… | |
| end | |
| diff --git a/spec/reports_as_sparkline_spec.rb b/spec/reports_as_sparkline_spec… | |
| @@ -69,7 +69,7 @@ end | |
| describe "Model#name_report should default to count operation on created at" do | |
| it "should call models count function" do | |
| - User.registrations_report.class.should == ActiveSupport::OrderedHash | |
| + User.registrations_report.class.should == Array | |
| end | |
| end | |
| @@ -77,7 +77,7 @@ end | |
| describe "Model#name_report should default to count operation on created at" do | |
| it "should call models count function" do | |
| - User.registrations_report.class.should == ActiveSupport::OrderedHash | |
| + User.registrations_report.class.should == Array | |
| end | |
| end | |
| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb | |
| @@ -6,6 +6,48 @@ rescue LoadError | |
| gem 'rspec' | |
| require 'spec' | |
| end | |
| - | |
| +require File.dirname(__FILE__) + '/boot' unless defined?(ActiveRecord) | |
| $:.unshift(File.dirname(__FILE__) + '/../lib') | |
| -require 'reports_as_sparkline' | |
| -\ No newline at end of file | |
| + | |
| +plugin_spec_dir = File.dirname(__FILE__) | |
| +ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log") | |
| + | |
| +databases = YAML::load(IO.read(plugin_spec_dir + "/db/database.yml")) | |
| +ActiveRecord::Base.establish_connection(databases[ENV["DB"] || "mysql"]) | |
| +load(File.join(plugin_spec_dir, "db", "schema.rb")) | |
| + | |
| + | |
| +require 'reports_as_sparkline' | |
| + | |
| +Spec::Runner.configure do |config| | |
| + # If you're not using ActiveRecord you should remove these | |
| + # lines, delete config/database.yml and disable :active_record | |
| + # in your config/boot.rb | |
| + #config.use_transactional_fixtures = true | |
| + #config.use_instantiated_fixtures = false | |
| + #config.fixture_path = File.dirname(__FILE__) + '/spec/fixtures/' | |
| + | |
| + # == Fixtures | |
| + # | |
| + # You can declare fixtures for each example_group like this: | |
| + # describe "...." do | |
| + # fixtures :table_a, :table_b | |
| + # | |
| + # Alternatively, if you prefer to declare them only once, you can | |
| + # do so right here. Just uncomment the next line and replace the fixture | |
| + # names with your fixtures. | |
| + # | |
| + # config.global_fixtures = :table_a, :table_b | |
| + # | |
| + # If you declare global fixtures, be aware that they will be declared | |
| + # for all of your examples, even those that don't use them. | |
| + # | |
| + # == Mock Framework | |
| + # | |
| + # RSpec uses it's own mocking framework by default. If you prefer to | |
| + # use mocha, flexmock or RR, uncomment the appropriate line: | |
| + # | |
| + # config.mock_with :mocha | |
| + # config.mock_with :flexmock | |
| + # config.mock_with :rr | |
| +end | |
| +\ No newline at end of file |