diff --git a/Gemfile b/Gemfile index 3e997ea..5fafe05 100644 --- a/Gemfile +++ b/Gemfile @@ -8,4 +8,5 @@ gem 'time_ext', '>= 0.2.6' group :development do gem 'rspec', '>= 2.0.1' gem 'yard', '>= 0.6.1' + gem 'i18n' end \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 3ec2c87..0a8a4bc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,6 +3,7 @@ GEM specs: activesupport (3.0.3) diff-lcs (1.1.2) + i18n (0.4.2) json (1.4.6) redis (2.1.1) rspec (2.1.0) @@ -22,6 +23,7 @@ PLATFORMS DEPENDENCIES activesupport (>= 2.3.0) + i18n json (>= 1.0.0) redis (>= 2.0.0) rspec (>= 2.0.1) diff --git a/lib/redistat.rb b/lib/redistat.rb index 143e38f..4d52389 100644 --- a/lib/redistat.rb +++ b/lib/redistat.rb @@ -1,11 +1,11 @@ require 'rubygems' require 'active_support' -require 'active_support/time' if !Time.respond_to?(:days_in_month) # Active Support 2.x and 3.x +require 'active_support/hash_with_indifferent_access' if !Hash.respond_to?(:with_indifferent_access) # Active Support 2.x and 3.x require 'redis' require 'date' require 'time' -require 'time/ext' +require 'time_ext' require 'json' require 'digest/sha1' diff --git a/lib/redistat/event.rb b/lib/redistat/event.rb index 9b55933..7ba3967 100644 --- a/lib/redistat/event.rb +++ b/lib/redistat/event.rb @@ -9,7 +9,7 @@ module Redistat attr_accessor :meta attr_accessor :options - def initialize(scope, label = nil, date = nil, stats = {}, meta = {}, options = {}, is_new = true) + def initialize(scope, label = nil, date = nil, stats = {}, options = {}, meta = {}, is_new = true) @options = default_options.merge(options) @key = Key.new(scope, label, date, @options) @stats = stats ||= {} diff --git a/lib/redistat/model.rb b/lib/redistat/model.rb index 07bd330..677c524 100644 --- a/lib/redistat/model.rb +++ b/lib/redistat/model.rb @@ -1,13 +1,50 @@ module Redistat - class Model + module Model - def self.create(*args) - Event.new(self.name, self.options, *args) + def self.included(base) + base.extend(self) end - def self.options + def store(label, stats = {}, date = nil, meta = {}, opts = {}) + Event.new(name, label, date, stats, options.merge(opts), meta).save + end + alias :event :store + + def fetch(label, from, till, opts = {}) + Finder.find({ + :scope => name, + :label => label, + :from => from, + :till => till + }.merge(options.merge(opts))) + end + alias :find :fetch + + def depth(depth = nil) + if !depth.nil? + options[:depth] = depth + else + options[:depth] || nil + end + end + + def store_event(boolean = nil) + if !boolean.nil? + options[:store_event] = boolean + else + options[:store_event] || nil + end + end + + def options @options ||= {} end + private + + def name + @name ||= self.to_s + end + end end \ No newline at end of file diff --git a/lib/redistat/result.rb b/lib/redistat/result.rb index e433055..68dea24 100644 --- a/lib/redistat/result.rb +++ b/lib/redistat/result.rb @@ -1,5 +1,5 @@ module Redistat - class Result < ::Hash + class Result < ::ActiveSupport::HashWithIndifferentAccess attr_accessor :from attr_accessor :till diff --git a/spec/event_spec.rb b/spec/event_spec.rb index 55cd2fa..14fd9e5 100644 --- a/spec/event_spec.rb +++ b/spec/event_spec.rb @@ -12,7 +12,7 @@ describe Redistat::Event do @meta = {:user_id => 239} @options = {:depth => :hour} @date = Time.now - @event = Redistat::Event.new(@scope, @label, @date, @stats, @meta, @options) + @event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta) end it "should initialize properly" do @@ -43,7 +43,7 @@ describe Redistat::Event do end it "should increment next_id" do - event = Redistat::Event.new("VisitorCount", @label, @date, @stats, @meta, @options) + event = Redistat::Event.new("VisitorCount", @label, @date, @stats, @options, @meta) @event.next_id.should == 1 event.next_id.should == 1 @event.next_id.should == 2 @@ -51,7 +51,7 @@ describe Redistat::Event do end it "should store event properly" do - @event = Redistat::Event.new(@scope, @label, @date, @stats, @meta, @options.merge({:store_event => true})) + @event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta) @event.new?.should be_true @event.save @event.new?.should be_false @@ -61,7 +61,7 @@ describe Redistat::Event do end it "should find event by id" do - @event = Redistat::Event.new(@scope, @label, @date, @stats, @meta, @options.merge({:store_event => true})).save + @event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta).save fetched = Redistat::Event.find(@scope, @event.id) @event.scope.should == fetched.scope @event.label.should == fetched.label @@ -70,7 +70,7 @@ describe Redistat::Event do it "should store summarized statistics" do 2.times do |i| - @event = Redistat::Event.new(@scope, @label, @date, @stats, @meta, @options).save + @event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta).save Redistat::Date::DEPTHS.each do |depth| summary = db.hgetall @event.key.to_s(depth) summary.should have_at_least(1).items diff --git a/spec/model_helper.rb b/spec/model_helper.rb new file mode 100644 index 0000000..fd31251 --- /dev/null +++ b/spec/model_helper.rb @@ -0,0 +1,15 @@ +require "redistat" + +class ModelHelper + include Redistat::Model + + +end + +class ModelHelper2 + include Redistat::Model + + depth :day + store_event true + +end \ No newline at end of file diff --git a/spec/model_spec.rb b/spec/model_spec.rb new file mode 100644 index 0000000..3894cf8 --- /dev/null +++ b/spec/model_spec.rb @@ -0,0 +1,60 @@ +require "spec_helper" +require "model_helper" + +describe Redistat::Model do + include Redistat::Database + + before(:each) do + db.flushdb + end + + it "should should name itself correctly" do + ModelHelper.send(:name).should == "ModelHelper" + ModelHelper2.send(:name).should == "ModelHelper2" + end + + it "should listen to model-defined options" do + ModelHelper2.depth.should == :day + ModelHelper2.store_event.should == true + + ModelHelper.depth.should == nil + ModelHelper.store_event.should == nil + ModelHelper.depth(:hour) + ModelHelper.depth.should == :hour + ModelHelper.store_event(true) + ModelHelper.store_event.should == true + ModelHelper.options[:depth] = nil + ModelHelper.options[:store_event] = nil + ModelHelper.depth.should == nil + ModelHelper.store_event.should == nil + end + + it "should store and fetch stats" do + ModelHelper.store("sheep.black", {:count => 6, :weight => 461}, 4.hours.ago) + ModelHelper.store("sheep.black", {:count => 2, :weight => 156}) + + stats = ModelHelper.fetch("sheep.black", 2.hours.ago, 1.hour.from_now) + stats.total["count"].should == 2 + stats.total["weight"].should == 156 + stats.first.should == stats.total + + stats = ModelHelper.fetch("sheep.black", 5.hours.ago, 1.hour.from_now) + stats.total[:count].should == 8 + stats.total[:weight].should == 617 + stats.first.should == stats.total + + ModelHelper.store("sheep.white", {:count => 5, :weight => 393}, 4.hours.ago) + ModelHelper.store("sheep.white", {:count => 4, :weight => 316}) + + stats = ModelHelper.fetch("sheep.white", 2.hours.ago, 1.hour.from_now) + stats.total[:count].should == 4 + stats.total[:weight].should == 316 + stats.first.should == stats.total + + stats = ModelHelper.fetch("sheep.white", 5.hours.ago, 1.hour.from_now) + stats.total[:count].should == 9 + stats.total[:weight].should == 709 + stats.first.should == stats.total + end + +end \ No newline at end of file