redis_record 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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