widescreen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ .DS_Store
18
+
19
+ Gemfile.lock
20
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - rbx
6
+ - jruby
7
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Marcin Ciunelis
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # Widescreen[![travis-ci](https://secure.travis-ci.org/martinciu/widescreen.png?branch=master)](http://travis-ci.org/martinciu/widescreen)
2
+ Rack based event statistic framework for any Rack app
3
+
4
+ ## Requirements
5
+
6
+ Widescreen uses redis as a datastore.
7
+
8
+ Widescreen only supports redis 2.0 or greater.
9
+
10
+ If you're on OS X, Homebrew is the simplest way to install Redis:
11
+
12
+ $ brew install redis
13
+ $ redis-server /usr/local/etc/redis.conf
14
+
15
+ You now have a Redis daemon running on 6379.
16
+
17
+ ## Setup
18
+
19
+ If you are using bundler add widescreen to your Gemfile:
20
+
21
+ gem 'widescreen'
22
+
23
+ Then run:
24
+
25
+ bundle install
26
+
27
+ Otherwise install the gem:
28
+
29
+ gem install widescreen
30
+
31
+ and require it in your project:
32
+
33
+ require 'widescreen'
34
+
35
+ ## Usage
36
+
37
+ Anywhere in you code call
38
+
39
+ Widescreen::Stat.add(:metric_name, 10)
40
+
41
+ to increase counter by 10 for `metric_name` metric or
42
+
43
+ Widescreen::Stat.add(:metric_name)
44
+
45
+ to increase it by 1
46
+
47
+ ## Web Interface
48
+
49
+ Web interface is on to-do list. It will be simple sinatra app similar to Resque web interface
50
+
51
+ ## Configuration
52
+
53
+ ### Redis
54
+
55
+ You may want to change the Redis host and port Wide connects to, or
56
+ set various other options at startup.
57
+
58
+ Widescreen has a `redis` setter which can be given a string or a Redis
59
+ object. This means if you're already using Redis in your app, Widescreen
60
+ can re-use the existing connection.
61
+
62
+ String: `Widescreen.redis = 'localhost:6379'`
63
+
64
+ Redis: `Widescreen.redis = $redis`
65
+
66
+ For our rails app we have a `config/initializers/widescreen.rb` file where
67
+ we load `config/widescreen.yml` by hand and set the Redis information
68
+ appropriately.
69
+
70
+ Here's our `config/widescreen.yml`:
71
+
72
+ development: localhost:6379
73
+ test: localhost:6379
74
+ staging: redis1.example.com:6379
75
+ fi: localhost:6379
76
+ production: redis1.example.com:6379
77
+
78
+ And our initializer:
79
+
80
+ rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
81
+ rails_env = ENV['RAILS_ENV'] || 'development'
82
+
83
+ widescreen_config = YAML.load_file(rails_root + '/config/widescreen.yml')
84
+ Widescreen.redis = widescreen_config[rails_env]
85
+
86
+ ## Namespaces
87
+
88
+ If you're running multiple, separate instances of widescreen you may want
89
+ to namespace the keyspaces so they do not overlap. This is not unlike
90
+ the approach taken by many memcached clients.
91
+
92
+ This feature is provided by the [redis-namespace][rs] library, which
93
+ widescreen uses by default to separate the keys it manages from other keys
94
+ in your Redis server.
95
+
96
+ Simply use the `Widescreen.redis.namespace` accessor:
97
+
98
+ Widescreen.redis.namespace = "widescreen:blog"
99
+
100
+ We recommend sticking this in your initializer somewhere after Redis
101
+ is configured.
102
+
103
+ ## Development
104
+
105
+ Source hosted at [GitHub](http://github.com/martinciu/widescreen).
106
+ Report Issues/Feature requests on [GitHub Issues](http://github.com/martinciu/widescreen/issues).
107
+
108
+ Tests can be ran with `rake test`
109
+
110
+ ### Note on Patches/Pull Requests
111
+
112
+ * Fork the project.
113
+ * Make your feature addition or bug fix.
114
+ * Add tests for it. This is important so I don't break it in a
115
+ future version unintentionally.
116
+ * Commit, do not mess with rakefile, version, or history.
117
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
118
+ * Send me a pull request. Bonus points for topic branches.
119
+
120
+ ## Copyright
121
+
122
+ Copyright (c) 2011 Marcin Ciunelis. See [LICENSE](https://github.com/martinciu/widescreen/blob/master/LICENSE) for details.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake/testtask'
2
+ require 'bundler/gem_tasks'
3
+ Bundler.setup(:default, :test)
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "spec"
7
+ t.test_files = FileList['spec/**/*_spec.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,58 @@
1
+ module Widescreen
2
+ class Metric
3
+ attr_accessor :name
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def new_record?
10
+ !Widescreen.redis.sismember(:metrics, name)
11
+ end
12
+
13
+ def save
14
+ return false unless valid?
15
+ Widescreen.redis.sadd(:metrics, name) if new_record?
16
+ true
17
+ end
18
+
19
+ def valid?
20
+ !name.empty?
21
+ end
22
+
23
+ def push(value)
24
+ Widescreen::Stat.add(self, value)
25
+ end
26
+
27
+ def stats
28
+ Widescreen.redis.keys("#{name}#{Widescreen::SEPARATOR}*").map { |s| Widescreen::Stat.find(s) }
29
+ end
30
+
31
+ def self.find(name)
32
+ new(name)
33
+ end
34
+
35
+ def to_s
36
+ name
37
+ end
38
+
39
+ def self.find_or_create(metric)
40
+ if Widescreen.redis.sismember(:metrics, metric)
41
+ find(metric)
42
+ else
43
+ create(metric)
44
+ end
45
+ end
46
+
47
+ def self.all
48
+ Widescreen.redis.smembers(:metrics).map {|m| find(m)}
49
+ end
50
+
51
+ def self.create(name)
52
+ metric = new(name)
53
+ metric.save
54
+ metric
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,38 @@
1
+ module Widescreen
2
+ class Stat
3
+ attr_accessor :metric, :time, :value
4
+
5
+ def initialize(metric, time, value = 1)
6
+ @metric = Widescreen::Metric.find_or_create(metric)
7
+ @time = time
8
+ @value = value
9
+ end
10
+
11
+ def save
12
+ Widescreen.redis.incrby(key, value)
13
+ end
14
+
15
+ def self.add(metric, value = 1)
16
+ new(metric, Time.now, value).save
17
+ end
18
+
19
+ def self.find(key)
20
+ value = Widescreen.redis.get(key)
21
+ return if value.nil?
22
+ metric_name, time = key.split(Widescreen::SEPARATOR, 2)
23
+ new(metric_name, Time.parse(time), value)
24
+ end
25
+
26
+ protected
27
+ def key
28
+ [metric.name, time_string].join(Widescreen::SEPARATOR)
29
+ end
30
+
31
+ def time_string
32
+ time.iso8601
33
+ rescue NoMethodError
34
+ time
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Widescreen
2
+ VERSION = "0.0.1"
3
+ end
data/lib/widescreen.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'redis/namespace'
2
+ require 'time'
3
+
4
+ require 'widescreen/version'
5
+ require 'widescreen/metric'
6
+ require 'widescreen/stat'
7
+
8
+ module Widescreen
9
+ SEPARATOR = "|"
10
+
11
+ extend self
12
+
13
+ # Accepts:
14
+ # 1. A 'hostname:port' String
15
+ # 2. A 'hostname:port:db' String (to select the Redis db)
16
+ # 3. A 'hostname:port/namespace' String (to set the Redis namespace)
17
+ # 4. A Redis URL String 'redis://host:port'
18
+ # 5. An instance of `Redis`, `Redis::Client`, `Redis::DistRedis`,
19
+ # or `Redis::Namespace`.
20
+ def redis=(server)
21
+ case server
22
+ when String
23
+ if server =~ /redis\:\/\//
24
+ redis = Redis.connect(:url => server, :thread_safe => true)
25
+ else
26
+ server, namespace = server.split('/', 2)
27
+ host, port, db = server.split(':')
28
+ redis = Redis.new(:host => host, :port => port,
29
+ :thread_safe => true, :db => db)
30
+ end
31
+ namespace ||= :resque
32
+
33
+ @redis = Redis::Namespace.new(namespace, :redis => redis)
34
+ when Redis::Namespace
35
+ @redis = server
36
+ else
37
+ @redis = Redis::Namespace.new(:resque, :redis => server)
38
+ end
39
+ end
40
+
41
+ # Returns the current Redis connection. If none has been created, will
42
+ # create a new one.
43
+ def redis
44
+ return @redis if @redis
45
+ self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
46
+ self.redis
47
+ end
48
+ end
@@ -0,0 +1,115 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./spec/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./spec/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Glue small output buffers together in order to send small replies in a
113
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
+ # in terms of number of queries per second. Use 'yes' if unsure.
115
+ glueoutputbuf yes
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ dir = File.dirname(File.expand_path(__FILE__))
7
+ $LOAD_PATH.unshift dir + '/../lib'
8
+ $TESTING = true
9
+ require 'minitest/autorun'
10
+ require 'timecop'
11
+
12
+ if !ENV['TRAVIS']
13
+
14
+ # make sure we can run redis
15
+
16
+ if !system("which redis-server")
17
+ puts '', "** can't find `redis-server` in your path"
18
+ puts "** try running `sudo rake install`"
19
+ abort ''
20
+ end
21
+
22
+ #
23
+ # start our own redis when the tests start,
24
+ # kill it when they end
25
+ #
26
+
27
+ at_exit do
28
+ next if $!
29
+
30
+ if defined?(MiniTest)
31
+ exit_code = MiniTest::Unit.new.run(ARGV)
32
+ else
33
+ exit_code = Test::Unit::AutoRunner.run
34
+ end
35
+
36
+ pid = `ps -A -o pid,command | grep [r]edis-test`.split(" ")[0]
37
+ puts "Killing test redis server..."
38
+ `rm -f #{dir}/dump.rdb`
39
+ Process.kill("KILL", pid.to_i)
40
+ exit exit_code
41
+ end
42
+
43
+ puts "Starting redis for testing at localhost:9736..."
44
+ `redis-server #{dir}/redis-test.conf`
45
+ Widescreen.redis = 'localhost:9736'
46
+ end
47
+
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Widescreen::Metric do
4
+
5
+ before(:each) do
6
+ Widescreen.redis.flushall
7
+ end
8
+
9
+ describe "instance methods" do
10
+ describe "initialize" do
11
+ it "set name" do
12
+ Widescreen::Metric.new("foo").name.must_equal "foo"
13
+ end
14
+ end
15
+
16
+ describe "save" do
17
+ it "saves valid record" do
18
+ metric = Widescreen::Metric.new("foo")
19
+ metric.save.must_equal true
20
+ Widescreen.redis.sismember(:metrics, "foo").must_equal true
21
+ end
22
+ it "doesn't save invalid record" do
23
+ metric = Widescreen::Metric.new("")
24
+ metric.save.must_equal false
25
+ Widescreen.redis.sismember(:metrics, "foo").must_equal false
26
+ end
27
+ end
28
+
29
+ describe "valid?" do
30
+ it "returns true if name is not empty" do
31
+ Widescreen::Metric.new("foo").valid?.must_equal true
32
+ end
33
+ it "returns false if name is empty" do
34
+ Widescreen::Metric.new("").valid?.must_equal false
35
+ end
36
+ end
37
+
38
+ describe "new_record?" do
39
+ before {@metric = Widescreen::Metric.new("foo")}
40
+ it { @metric.new_record?.must_equal true }
41
+
42
+ it "knows when it is an existed record" do
43
+ @metric.save
44
+ @metric.new_record?.must_equal false
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ describe "class methods" do
51
+ describe "create" do
52
+ before { @metric = Widescreen::Metric.create("foo") }
53
+ it { Widescreen.redis.sismember(:metrics, "foo").must_equal true }
54
+ it { @metric.must_be_instance_of Widescreen::Metric }
55
+ end
56
+
57
+ describe "all" do
58
+ before(:each) do
59
+ Widescreen::Metric.create("foo")
60
+ Widescreen::Metric.create("bar")
61
+ Widescreen::Metric.create("baz")
62
+ end
63
+
64
+ it { Widescreen::Metric.all.must_be_instance_of Array }
65
+ it { Widescreen::Metric.all.size.must_equal 3 }
66
+ it "returns array of Metrics" do
67
+ Widescreen::Metric.all.each do |metric|
68
+ metric.must_be_instance_of Widescreen::Metric
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "stats" do
74
+ before(:each) do
75
+ @metric = Widescreen::Metric.create("foo")
76
+ now = Time.now
77
+ [1, 2, 5].each do |n|
78
+ Timecop.freeze(now - n*3600) do
79
+ Widescreen::Stat.add("foo")
80
+ end
81
+ end
82
+ Timecop.freeze(now)
83
+ end
84
+
85
+ after(:each) do
86
+ Timecop.return
87
+ end
88
+
89
+ it { @metric.stats.size.must_equal 3 }
90
+ it { @metric.stats.must_be_instance_of Array}
91
+
92
+ it "returns instances of Stat" do
93
+ @metric.stats.each do |m|
94
+ m.must_be_instance_of Widescreen::Stat
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Widescreen::Stat do
4
+ before(:each) do
5
+ Widescreen.redis.flushall
6
+ end
7
+
8
+ describe "instance methods" do
9
+ describe "initialize" do
10
+ before(:each) do
11
+ Timecop.freeze
12
+ @metric = Widescreen::Metric.create("foo")
13
+ @time = Time.now.iso8601
14
+ @stat = Widescreen::Stat.new("foo", @time, 5)
15
+ end
16
+
17
+ after(:each) do
18
+ Timecop.return
19
+ end
20
+
21
+ it "has metric" do
22
+ @stat.metric.must_be_instance_of Widescreen::Metric
23
+ end
24
+
25
+ it "has time" do
26
+ @stat.time.must_equal @time
27
+ end
28
+
29
+ it "has value" do
30
+ @stat.value.must_equal 5
31
+ end
32
+ end
33
+
34
+ describe "find" do
35
+ before(:each) do
36
+ @key = ["foo", Time.now.strftime('%Y-%m-%dT%H')].join(Widescreen::SEPARATOR)
37
+ Widescreen.redis.set(@key, 10)
38
+ end
39
+
40
+ it "returns instance of Stat if it exist" do
41
+ Widescreen::Stat.find(@key).must_be_instance_of Widescreen::Stat
42
+ end
43
+
44
+ it "returns nil if not found" do
45
+ Widescreen::Stat.find("#{@key}1").must_be_nil
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ describe "class methods" do
52
+ describe "add" do
53
+ before(:each) do
54
+ Timecop.freeze
55
+ @time = Time.now.iso8601
56
+ @metric_name = "foo"
57
+ Widescreen::Metric.create(@metric_name)
58
+ @key = [@metric_name, @time].join(Widescreen::SEPARATOR)
59
+ end
60
+
61
+ after(:each) do
62
+ Timecop.return
63
+ end
64
+
65
+ describe "when no entry for a given time" do
66
+ it "creates entry with default value" do
67
+ Widescreen::Stat.add(@metric_name)
68
+ Widescreen.redis.get(@key).must_equal "1"
69
+ end
70
+
71
+ it "creates entry with value" do
72
+ Widescreen::Stat.add(@metric_name, 5)
73
+ Widescreen.redis.get(@key).must_equal "5"
74
+ end
75
+ end
76
+
77
+ describe "when there is an entry for a given time" do
78
+ before(:each) do
79
+ Widescreen::Stat.add(@metric_name, 5)
80
+ end
81
+
82
+ it "updates entry with default value" do
83
+ Widescreen::Stat.add(@metric_name)
84
+ Widescreen.redis.get(@key).must_equal "6"
85
+ end
86
+
87
+ it "updates entry with value" do
88
+ Widescreen::Stat.add(@metric_name, 5)
89
+ Widescreen.redis.get(@key).must_equal "10"
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ require 'widescreen/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "widescreen"
8
+ s.version = Widescreen::VERSION
9
+ s.authors = ["Marcin Ciunelis"]
10
+ s.email = "marcin.ciunelis@gmail.com"
11
+ s.homepage = "http://github.com/martinciu/widescreen"
12
+ s.summary = "Rack based event statistic framework for any Rack app"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ s.platform = Gem::Platform::RUBY
19
+
20
+ s.add_dependency 'redis', '~> 2.2.2'
21
+ s.add_dependency 'redis-namespace', '~> 1.0.3'
22
+ s.add_development_dependency 'rake'
23
+ s.add_development_dependency 'minitest', '~> 2.6.1'
24
+ s.add_development_dependency 'timecop', '~> 0.3.5'
25
+
26
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: widescreen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marcin Ciunelis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-21 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: &2162119200 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.2.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2162119200
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis-namespace
27
+ requirement: &2162118580 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.3
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2162118580
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &2162118160 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2162118160
47
+ - !ruby/object:Gem::Dependency
48
+ name: minitest
49
+ requirement: &2162117460 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.6.1
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2162117460
58
+ - !ruby/object:Gem::Dependency
59
+ name: timecop
60
+ requirement: &2162096100 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.3.5
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2162096100
69
+ description:
70
+ email: marcin.ciunelis@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - .gitignore
76
+ - .travis.yml
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - lib/widescreen.rb
82
+ - lib/widescreen/metric.rb
83
+ - lib/widescreen/stat.rb
84
+ - lib/widescreen/version.rb
85
+ - spec/redis-test.conf
86
+ - spec/spec_helper.rb
87
+ - spec/widescreen/metric_spec.rb
88
+ - spec/widescreen/stat_spec.rb
89
+ - widescreen.gemspec
90
+ homepage: http://github.com/martinciu/widescreen
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ segments:
103
+ - 0
104
+ hash: 225638225036064920
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ segments:
112
+ - 0
113
+ hash: 225638225036064920
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 1.8.10
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: Rack based event statistic framework for any Rack app
120
+ test_files:
121
+ - spec/redis-test.conf
122
+ - spec/spec_helper.rb
123
+ - spec/widescreen/metric_spec.rb
124
+ - spec/widescreen/stat_spec.rb