redis_record 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ .bundle
2
+ pkg
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm @redis_record
2
+ bundle install
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :gemcutter
2
+
3
+ gem 'rake'
4
+ gem 'redis'
5
+
6
+ group :test do
7
+ gem 'minitest'
8
+ gem 'watchr'
9
+ gem 'jeweler'
10
+ end
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ gemcutter (0.6.1)
5
+ git (1.2.5)
6
+ jeweler (1.4.0)
7
+ gemcutter (>= 0.1.0)
8
+ git (>= 1.2.5)
9
+ rubyforge (>= 2.0.0)
10
+ json_pure (1.4.6)
11
+ minitest (1.7.2)
12
+ rake (0.8.7)
13
+ redis (2.0.10)
14
+ rubyforge (2.0.4)
15
+ json_pure (>= 1.1.7)
16
+ watchr (0.7)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ jeweler
23
+ minitest
24
+ rake
25
+ redis
26
+ watchr
@@ -0,0 +1,22 @@
1
+ = RedisRecord
2
+
3
+ ActiveRecord-like API for Objects stored in Redis.
4
+
5
+ == Usage
6
+
7
+ require 'lib/redis_record'
8
+
9
+ class User
10
+ attr_accessor :email, :username
11
+
12
+ extend RedisRecord
13
+ use_redis
14
+ end
15
+
16
+ u = User.new
17
+ u.email = "email@example.com"
18
+ u.username = "thk"
19
+ u.save
20
+ puts u.id # => 1
21
+
22
+ u_new = User.find(1)
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+
7
+ task :default => :test
8
+
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << "test"
11
+ t.ruby_opts << "-rubygems"
12
+ t.test_files = FileList['test/test*.rb']
13
+ t.verbose = true
14
+ end
15
+
16
+ namespace :test do
17
+ desc "Run tests VERBOSE"
18
+ task :verbose do
19
+ # TODO pass task arguments in a better way
20
+ ENV['TESTOPTS'] = "-v"
21
+ Rake::Task[:test].invoke
22
+ end
23
+
24
+ task :watchr do
25
+ system "./test.watchr"
26
+ end
27
+ end
28
+
29
+ begin
30
+ require 'jeweler'
31
+ Jeweler::Tasks.new do |gemspec|
32
+ gemspec.name = "redis_record"
33
+ gemspec.summary = "One line summary of your gem"
34
+ # gemspec.description = "TODO"
35
+ gemspec.email = "peter-redis_record@suschlik.de"
36
+ gemspec.homepage = "http://github.com/splattael/redis_record"
37
+ gemspec.authors = ["Thomas Kerstgens", "Peter Suschlik"]
38
+ gemspec.add_dependency 'redis', '~> 2.0.0'
39
+ end
40
+ Jeweler::GemcutterTasks.new
41
+ rescue LoadError
42
+ puts "Jeweler not available. Install it with: gem install jeweler"
43
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,66 @@
1
+ require 'redis'
2
+
3
+ module RedisRecord
4
+ @@redis = nil
5
+
6
+ # call this to mixin member-methods
7
+ # TODO: redis parameters (host, port, etc.)
8
+ def use_redis(*args)
9
+ class_eval do
10
+ attr_accessor :id
11
+
12
+ def save
13
+ unless persisted?
14
+ # Note: redis automatically generates an key_value-pair with type int
15
+ self.id = self.class.redis.incr('#' + self.class.redis_key)
16
+ end
17
+ "OK" == self.class.redis.set(self.class.redis_key(id), self.dump)
18
+ end
19
+
20
+ def persisted?
21
+ !id.nil?
22
+ end
23
+
24
+ protected
25
+
26
+ def dump
27
+ Marshal.dump(self)
28
+ end
29
+ end
30
+
31
+ @@redis = Redis.new(*args)
32
+ end
33
+
34
+ def redis
35
+ @@redis
36
+ end
37
+
38
+ def redis_key(*args)
39
+ # redis_key -> user
40
+ # redis_key(1) -> user_1
41
+ # redis_key(1, "attr") -> user_1_attr
42
+ [ @_prefix ||= self.name.downcase, *args ].join('_')
43
+ end
44
+
45
+ def find(id)
46
+ data = redis.get(redis_key(id))
47
+ parse(data) if data
48
+ end
49
+
50
+ def all
51
+ keys = redis.keys(redis_key("*"))
52
+ objects = []
53
+ keys.each do |key|
54
+ if data = redis.get(key)
55
+ objects << parse(data)
56
+ end
57
+ end
58
+ objects
59
+ end
60
+
61
+ protected
62
+
63
+ def parse(data)
64
+ Marshal.load(data)
65
+ end
66
+ end
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{redis_record}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Thomas Kerstgens", "Peter Suschlik"]
12
+ s.date = %q{2010-10-04}
13
+ s.email = %q{peter-redis_record@suschlik.de}
14
+ s.extra_rdoc_files = [
15
+ "README.rdoc"
16
+ ]
17
+ s.files = [
18
+ ".gitignore",
19
+ ".rvmrc",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "lib/redis_record.rb",
26
+ "redis_record.gemspec",
27
+ "test.watchr",
28
+ "test/helper.rb",
29
+ "test/test_redis_record.rb",
30
+ "test/test_redis_record_real.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/splattael/redis_record}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.7}
36
+ s.summary = %q{One line summary of your gem}
37
+ s.test_files = [
38
+ "test/helper.rb",
39
+ "test/test_redis_record.rb",
40
+ "test/test_redis_record_real.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_runtime_dependency(%q<redis>, ["~> 2.0.0"])
49
+ else
50
+ s.add_dependency(%q<redis>, ["~> 2.0.0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<redis>, ["~> 2.0.0"])
54
+ end
55
+ end
56
+
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env watchr
2
+
3
+ def run(cmd)
4
+ puts(cmd)
5
+ system cmd
6
+ end
7
+
8
+ def run_test_file(file)
9
+ clear
10
+ run "ruby -rubygems -Ilib:test #{file}"
11
+ end
12
+
13
+ def run_tests
14
+ clear
15
+ run "rake"
16
+ end
17
+
18
+ def clear
19
+ system "clear"
20
+ end
21
+
22
+ def underscore(file)
23
+ file.gsub('/', '_')
24
+ end
25
+
26
+ @interrupted = false
27
+
28
+ Signal.trap 'QUIT' do
29
+ run_tests
30
+ end
31
+
32
+ Signal.trap 'INT' do
33
+ if @interrupted then
34
+ abort("\n")
35
+ else
36
+ puts "Interrupt a second time to quit"
37
+ @interrupted = true
38
+ Kernel.sleep 1.5
39
+ # raise Interrupt, nil # let the run loop catch it
40
+ run_tests
41
+ end
42
+ end
43
+
44
+ run_tests
45
+
46
+ watch('test/test_.*\.rb') {|md| run_test_file md[0] }
47
+ watch('lib/(.*)\.rb') {|md| run_test_file "test/test_#{underscore(md[1])}.rb" }
48
+ watch('test/helper.rb') { run_tests }
49
+
@@ -0,0 +1,20 @@
1
+ require 'redis_record'
2
+
3
+ require 'minitest/unit'
4
+ require 'minitest/spec'
5
+ require 'minitest/mock'
6
+
7
+ # Magically run tests at exit.
8
+ MiniTest::Unit.autorun
9
+
10
+ module MockedRedis
11
+ def setup
12
+ @redis = MiniTest::Mock.new
13
+ # TODO should defined on User class!
14
+ RedisRecord.send(:class_variable_set, :@@redis, @redis)
15
+ end
16
+
17
+ def teardown
18
+ @redis.verify
19
+ end
20
+ end
@@ -0,0 +1,103 @@
1
+ require 'helper'
2
+
3
+ class User < Struct.new(:name)
4
+ extend RedisRecord
5
+ use_redis
6
+ end
7
+
8
+ class TestRedisMocked < MiniTest::Unit::TestCase
9
+ include MockedRedis
10
+
11
+ def test_mocked_redis
12
+ assert_same @redis, User.redis
13
+ end
14
+ end
15
+
16
+ class TestRedisRecordUser < MiniTest::Unit::TestCase
17
+ def test_has_name
18
+ user = User.new("foo")
19
+
20
+ assert_equal "foo", user.name
21
+ user.name = "bar"
22
+ assert_equal "bar", user.name
23
+ end
24
+
25
+ def test_has_id
26
+ user = User.new("foo")
27
+
28
+ assert_nil user.id
29
+ assert !user.persisted?
30
+
31
+ user.id = 1
32
+ assert_equal 1, user.id
33
+ assert user.persisted?
34
+ end
35
+
36
+ def test_redis_key
37
+ assert_equal "user", User.redis_key
38
+ assert_equal "user_1", User.redis_key(1)
39
+ assert_equal "user_*", User.redis_key("*")
40
+ end
41
+ end
42
+
43
+ class TestRedisRecordEmpty < MiniTest::Unit::TestCase
44
+ include MockedRedis
45
+
46
+ def test_does_not_find_user
47
+ @redis.expect :get, nil, ["user_1"]
48
+
49
+ user = User.find(1)
50
+ assert_nil user
51
+ end
52
+
53
+ def test_no_users_at_all
54
+ @redis.expect :keys, [], ["user_*"]
55
+
56
+ users = User.all
57
+ assert_equal [], users
58
+ end
59
+ end
60
+
61
+ class TestRedisRecordNonEmpty < MiniTest::Unit::TestCase
62
+ include MockedRedis
63
+
64
+ def setup
65
+ super # mock redis
66
+ @user = User.new("foo")
67
+ @dump = @user.send(:dump)
68
+ end
69
+
70
+ def test_finds_user
71
+ @redis.expect :get, @dump, ["user_1"]
72
+
73
+ found = User.find(1)
74
+ assert_equal @user.name, found.name
75
+ end
76
+
77
+ def test_find_all_users
78
+ @redis.expect :keys, ["user_1"], ["user_*"]
79
+ @redis.expect :get, @dump, ["user_1"]
80
+
81
+ found = User.all
82
+ assert_equal 1, found.size
83
+ assert_equal @user.name, found.first.name
84
+ end
85
+
86
+ def test_saves_new_user
87
+ assert_nil @user.id
88
+
89
+ @redis.expect :incr, 3, ["#user"]
90
+ @user.id = 3 # for the dump
91
+ @redis.expect :set, "OK", ["user_3", @user.send(:dump)]
92
+ @user.id = nil
93
+
94
+ assert @user.save
95
+ end
96
+
97
+ def test_save_fails
98
+ @user.id = 23
99
+
100
+ @redis.expect :set, "NOT OK", ["user_23", @user.send(:dump)]
101
+ assert !@user.save
102
+ end
103
+ end
@@ -0,0 +1,71 @@
1
+ require 'helper'
2
+
3
+ class RealUser < Struct.new(:name)
4
+ extend RedisRecord
5
+ use_redis(:db => 2)
6
+ end
7
+
8
+ redis_server_running = \
9
+ begin
10
+ # Start with a fresh db
11
+ "PONG" == RealUser.redis.ping
12
+ rescue => e
13
+ puts e
14
+ false
15
+ end
16
+
17
+ if redis_server_running
18
+
19
+ class TestRealRedis < MiniTest::Unit::TestCase
20
+ def setup
21
+ RealUser.redis.flushall
22
+ @alice = RealUser.new("alice")
23
+ @bob = RealUser.new("bob")
24
+ end
25
+
26
+ def test_uses_test_db_as_option
27
+ assert_equal 2, RealUser.redis.client.db
28
+ end
29
+
30
+ def test_real_user
31
+ assert_equal "realuser", RealUser.redis_key
32
+ end
33
+
34
+ def test_empty
35
+ assert_equal [], RealUser.all
36
+ assert_nil RealUser.find(1)
37
+ end
38
+
39
+ def test_find
40
+ assert @alice.save
41
+
42
+ assert_nil RealUser.find(-1)
43
+ assert_equal @alice, RealUser.find(@alice.id)
44
+ end
45
+
46
+ def test_all
47
+ assert @alice.save
48
+ assert @bob.save
49
+
50
+ assert_equal [@alice, @bob], RealUser.all
51
+ end
52
+
53
+ def test_save_and_update
54
+ assert @alice.save
55
+ assert_equal 1, @alice.id
56
+
57
+ @alice.name = "Ali"
58
+ assert @alice.save
59
+ assert_equal 1, @alice.id
60
+ assert_equal @alice, RealUser.find(@alice.id)
61
+
62
+ assert @bob.save
63
+ assert_equal 2, @bob.id
64
+ end
65
+ end
66
+
67
+ else
68
+
69
+ puts "SKIP: Redis server not running!"
70
+
71
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_record
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Thomas Kerstgens
14
+ - Peter Suschlik
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-04 00:00:00 +02:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 15
29
+ segments:
30
+ - 2
31
+ - 0
32
+ - 0
33
+ version: 2.0.0
34
+ requirement: *id001
35
+ prerelease: false
36
+ type: :runtime
37
+ name: redis
38
+ description:
39
+ email: peter-redis_record@suschlik.de
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - README.rdoc
46
+ files:
47
+ - .gitignore
48
+ - .rvmrc
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - README.rdoc
52
+ - Rakefile
53
+ - VERSION
54
+ - lib/redis_record.rb
55
+ - redis_record.gemspec
56
+ - test.watchr
57
+ - test/helper.rb
58
+ - test/test_redis_record.rb
59
+ - test/test_redis_record_real.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/splattael/redis_record
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --charset=UTF-8
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: One line summary of your gem
94
+ test_files:
95
+ - test/helper.rb
96
+ - test/test_redis_record.rb
97
+ - test/test_redis_record_real.rb