blendris 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +4 -0
- data/Manifest +32 -0
- data/PostInstall.txt +1 -0
- data/README.rdoc +79 -0
- data/Rakefile +22 -0
- data/autotest/discover.rb +3 -0
- data/blendris.gemspec +32 -0
- data/lib/blendris.rb +25 -0
- data/lib/blendris/accessor.rb +62 -0
- data/lib/blendris/errors.rb +3 -0
- data/lib/blendris/integer.rb +19 -0
- data/lib/blendris/list.rb +37 -0
- data/lib/blendris/model.rb +141 -0
- data/lib/blendris/node.rb +46 -0
- data/lib/blendris/reference.rb +51 -0
- data/lib/blendris/reference_base.rb +68 -0
- data/lib/blendris/reference_set.rb +65 -0
- data/lib/blendris/set.rb +39 -0
- data/lib/blendris/string.rb +19 -0
- data/lib/blendris/types.rb +14 -0
- data/lib/blendris/utils.rb +39 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/list_spec.rb +17 -0
- data/spec/model_spec.rb +180 -0
- data/spec/redis-tools_spec.rb +15 -0
- data/spec/ref_spec.rb +40 -0
- data/spec/set_spec.rb +20 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/string_spec.rb +20 -0
- data/tasks/rspec.rake +21 -0
- metadata +128 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
Binary file
|
data/History.txt
ADDED
data/Manifest
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
autotest/discover.rb
|
7
|
+
lib/blendris.rb
|
8
|
+
lib/blendris/accessor.rb
|
9
|
+
lib/blendris/errors.rb
|
10
|
+
lib/blendris/integer.rb
|
11
|
+
lib/blendris/list.rb
|
12
|
+
lib/blendris/model.rb
|
13
|
+
lib/blendris/node.rb
|
14
|
+
lib/blendris/reference.rb
|
15
|
+
lib/blendris/reference_base.rb
|
16
|
+
lib/blendris/reference_set.rb
|
17
|
+
lib/blendris/set.rb
|
18
|
+
lib/blendris/string.rb
|
19
|
+
lib/blendris/types.rb
|
20
|
+
lib/blendris/utils.rb
|
21
|
+
script/console
|
22
|
+
script/destroy
|
23
|
+
script/generate
|
24
|
+
spec/list_spec.rb
|
25
|
+
spec/model_spec.rb
|
26
|
+
spec/redis-tools_spec.rb
|
27
|
+
spec/ref_spec.rb
|
28
|
+
spec/set_spec.rb
|
29
|
+
spec/spec.opts
|
30
|
+
spec/spec_helper.rb
|
31
|
+
spec/string_spec.rb
|
32
|
+
tasks/rspec.rake
|
data/PostInstall.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
For more information on blendris, see http://github.com/alexmchale/blendris
|
data/README.rdoc
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
= blendris
|
2
|
+
|
3
|
+
* http://github.com/alexmchale/blendris
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Blendris is a Ruby interface to a Redis database.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
== SYNOPSIS:
|
12
|
+
|
13
|
+
== REQUIREMENTS:
|
14
|
+
|
15
|
+
* Blendris uses the redis RubyGem.
|
16
|
+
|
17
|
+
== INSTALL:
|
18
|
+
|
19
|
+
* gem install blendris
|
20
|
+
|
21
|
+
== EXAMPLES:
|
22
|
+
|
23
|
+
The following would create a Website model that knows its url and
|
24
|
+
paths within the website.
|
25
|
+
|
26
|
+
class Website < Blendris::Model
|
27
|
+
key "website", :title
|
28
|
+
|
29
|
+
string :title
|
30
|
+
string :url
|
31
|
+
set :paths
|
32
|
+
end
|
33
|
+
|
34
|
+
website = Website.create("One Fake Website")
|
35
|
+
website.url = "http://fakewebsite.com"
|
36
|
+
website.paths << "/blog/index"
|
37
|
+
website.paths << "/admin/index"
|
38
|
+
|
39
|
+
The above would create the following Redis keys:
|
40
|
+
|
41
|
+
website:One_Fake_Website => "Website" (This identifies the model type)
|
42
|
+
website:One_Fake_Website:name => "One Fake Website"
|
43
|
+
website:One_Fake_Website:url => "http://fakewebsite.com"
|
44
|
+
website:One_Fake_Website:paths => [ "/blog/index", "/admin/index" ]
|
45
|
+
|
46
|
+
Now suppose we want to open the Website model back up to add a concept of sister sites:
|
47
|
+
|
48
|
+
class Website
|
49
|
+
refs :sister_sites, :class => Website, :reverse => :sister_sites
|
50
|
+
end
|
51
|
+
|
52
|
+
This will cause the website to maintain a set of other websites. The reverse tag
|
53
|
+
causes the other website's sister_sites set to be updated when it is added or removed
|
54
|
+
from this site's list.
|
55
|
+
|
56
|
+
== LICENSE:
|
57
|
+
|
58
|
+
(The MIT License)
|
59
|
+
|
60
|
+
Copyright (c) 2010 Alexander Timothy McHale
|
61
|
+
|
62
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
63
|
+
a copy of this software and associated documentation files (the
|
64
|
+
'Software'), to deal in the Software without restriction, including
|
65
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
66
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
67
|
+
permit persons to whom the Software is furnished to do so, subject to
|
68
|
+
the following conditions:
|
69
|
+
|
70
|
+
The above copyright notice and this permission notice shall be
|
71
|
+
included in all copies or substantial portions of the Software.
|
72
|
+
|
73
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
74
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
75
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
76
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
77
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
78
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
79
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
gem "echoe", ">= 4.1"
|
4
|
+
gem "redis", ">= 0.1.2"
|
5
|
+
|
6
|
+
require "echoe"
|
7
|
+
|
8
|
+
require 'fileutils'
|
9
|
+
require './lib/blendris'
|
10
|
+
|
11
|
+
Echoe.new("blendris", "0.0.1") do |p|
|
12
|
+
|
13
|
+
p.description = "A redis library for Ruby"
|
14
|
+
p.url = "http://github.com/alexmchale/blendris"
|
15
|
+
p.author = "Alex McHale"
|
16
|
+
p.email = "alexmchale@gmail.com"
|
17
|
+
p.ignore_pattern = [ "tmp", "pkg", "script" ]
|
18
|
+
p.development_dependencies = []
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
data/blendris.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{blendris}
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Alex McHale"]
|
9
|
+
s.cert_chain = ["/Users/amchale/Dropbox/Security/gem-public_cert.pem"]
|
10
|
+
s.date = %q{2010-02-11}
|
11
|
+
s.description = %q{A redis library for Ruby}
|
12
|
+
s.email = %q{alexmchale@gmail.com}
|
13
|
+
s.extra_rdoc_files = ["README.rdoc", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb", "tasks/rspec.rake"]
|
14
|
+
s.files = ["History.txt", "Manifest", "PostInstall.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb", "script/console", "script/destroy", "script/generate", "spec/list_spec.rb", "spec/model_spec.rb", "spec/redis-tools_spec.rb", "spec/ref_spec.rb", "spec/set_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/string_spec.rb", "tasks/rspec.rake", "blendris.gemspec"]
|
15
|
+
s.homepage = %q{http://github.com/alexmchale/blendris}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Blendris", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{blendris}
|
19
|
+
s.rubygems_version = %q{1.3.5}
|
20
|
+
s.signing_key = %q{/Users/amchale/Dropbox/Security/gem-private_key.pem}
|
21
|
+
s.summary = %q{A redis library for Ruby}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
data/lib/blendris.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module Blendris
|
5
|
+
VERSION = '0.0.1'
|
6
|
+
end
|
7
|
+
|
8
|
+
require "blendris/errors"
|
9
|
+
require "blendris/utils"
|
10
|
+
|
11
|
+
require "blendris/accessor"
|
12
|
+
require "blendris/node"
|
13
|
+
|
14
|
+
require "blendris/model"
|
15
|
+
|
16
|
+
require "blendris/string"
|
17
|
+
require "blendris/integer"
|
18
|
+
require "blendris/list"
|
19
|
+
require "blendris/set"
|
20
|
+
|
21
|
+
require "blendris/reference_base"
|
22
|
+
require "blendris/reference"
|
23
|
+
require "blendris/reference_set"
|
24
|
+
|
25
|
+
require "blendris/types"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Blendris
|
4
|
+
|
5
|
+
module RedisAccessor
|
6
|
+
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
def redis
|
10
|
+
RedisAccessor.redis
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.redis
|
14
|
+
$_redis_connection ||= Redis.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def prefix
|
18
|
+
RedisAccessor.prefix
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_key(klass, values)
|
22
|
+
value_index = 0
|
23
|
+
|
24
|
+
klass.local_parameters.map do |symbol|
|
25
|
+
case symbol
|
26
|
+
|
27
|
+
when String then symbol
|
28
|
+
|
29
|
+
when Symbol
|
30
|
+
value = values[value_index]
|
31
|
+
value_index += 1
|
32
|
+
|
33
|
+
raise ArgumentError.new("#{self.name} created without #{symbol}") unless value
|
34
|
+
|
35
|
+
klass.cast_value symbol, value
|
36
|
+
|
37
|
+
else
|
38
|
+
raise TypeError.new("only strings and symbols allowed in key definition for #{klass.name} (#{symbol.class.name})")
|
39
|
+
|
40
|
+
end
|
41
|
+
end.map do |segment|
|
42
|
+
sanitize_key segment
|
43
|
+
end.compact.join(":")
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.prefix
|
47
|
+
$_redis_prefix ||= ""
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.prefix=(prefix)
|
51
|
+
$_redis_prefix = prefix.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.flush_keys
|
55
|
+
redis.keys("#{prefix}*").each do |key|
|
56
|
+
redis.del key
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Blendris
|
2
|
+
|
3
|
+
class RedisInteger
|
4
|
+
|
5
|
+
include RedisNode
|
6
|
+
|
7
|
+
def self.cast_to_redis(value, options = {})
|
8
|
+
raise TypeError.new("#{value.class.name} is not an integer") unless value.kind_of? Fixnum
|
9
|
+
|
10
|
+
value
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.cast_from_redis(value, options = {})
|
14
|
+
value.to_i if value
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Blendris
|
2
|
+
|
3
|
+
class RedisList
|
4
|
+
|
5
|
+
include RedisNode
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(key, options = {})
|
9
|
+
@key = key.to_s
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
redis.lrange(key, 0, -1).each do |value|
|
15
|
+
yield value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(value)
|
20
|
+
[ value ].flatten.compact.each do |v|
|
21
|
+
redis.rpush key, v
|
22
|
+
end
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def get
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete(value)
|
32
|
+
redis.lrem key, 0, value
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Blendris
|
2
|
+
|
3
|
+
class Model
|
4
|
+
|
5
|
+
include RedisAccessor
|
6
|
+
|
7
|
+
attr_reader :key
|
8
|
+
|
9
|
+
def initialize(new_key, options = {})
|
10
|
+
@key = sanitize_key(new_key)
|
11
|
+
actual_type = constantize(redis.get(prefix + key))
|
12
|
+
|
13
|
+
raise ArgumentError.new("#{self.class.name} second argument must be a hash") unless options.kind_of? Hash
|
14
|
+
raise TypeError.new("#{prefix + key} does not exist, not a #{self.class.name} - you may want create instead of new") if !actual_type
|
15
|
+
raise TypeError.new("#{prefix + key} is a #{actual_type}, not a #{self.class.name}") if actual_type != self.class
|
16
|
+
|
17
|
+
if options[:verify] != false
|
18
|
+
parameters = self.class.local_parameters.find_all {|s| s.kind_of? Symbol}
|
19
|
+
dne = parameters.find {|p| not self.send(p.to_s)}
|
20
|
+
|
21
|
+
raise ArgumentError.new("#{self.class.name} #{key} is missing its #{dne}") if dne
|
22
|
+
raise ArgumentError.new("blank keys are not allowed") if @key.length == 0
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def id
|
27
|
+
Digest::SHA1.hexdigest key
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(method_sym, *arguments)
|
31
|
+
(name, setter) = method_sym.to_s.scan(/(.*[^=])(=)?/).first
|
32
|
+
|
33
|
+
if node = redis_symbol(name)
|
34
|
+
if setter
|
35
|
+
return node.set *arguments
|
36
|
+
else
|
37
|
+
return node.get
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def redis_symbol(name)
|
45
|
+
subkey = self.subkey(name)
|
46
|
+
|
47
|
+
options = self.class.redis_symbols[name.to_s]
|
48
|
+
|
49
|
+
return unless options
|
50
|
+
|
51
|
+
options = options.merge(:model => self)
|
52
|
+
|
53
|
+
options[:type].new subkey, options
|
54
|
+
end
|
55
|
+
|
56
|
+
def subkey(key)
|
57
|
+
sanitize_key "#{self.key}:#{key}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def ==(other)
|
61
|
+
return false unless self.class == other.class
|
62
|
+
return self.key == other.key
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
|
67
|
+
include RedisAccessor
|
68
|
+
|
69
|
+
# This method will instantiate a new object with the correct key
|
70
|
+
# and assign the values passed to it.
|
71
|
+
def create(*args)
|
72
|
+
parameters = local_parameters.find_all {|s| s.kind_of? Symbol}
|
73
|
+
got = args.count
|
74
|
+
wanted = parameters.count
|
75
|
+
|
76
|
+
if got != wanted
|
77
|
+
msg = "wrong number of arguments for a new #{self.class.name} (%d for %d)" % [ got, wanted ]
|
78
|
+
raise ArgumentError.new(msg)
|
79
|
+
end
|
80
|
+
|
81
|
+
key = generate_key(self, args)
|
82
|
+
current_model = redis.get(prefix + key)
|
83
|
+
|
84
|
+
if current_model && current_model != self.name
|
85
|
+
raise ArgumentError.new("#{key} is a #{current_model}, not a #{self.name}")
|
86
|
+
end
|
87
|
+
|
88
|
+
redis.set(prefix + key, self.name)
|
89
|
+
|
90
|
+
obj = new(key, :verify => false)
|
91
|
+
|
92
|
+
parameters.each_with_index do |parm, i|
|
93
|
+
obj.redis_symbol(parm).set args[i]
|
94
|
+
end
|
95
|
+
|
96
|
+
obj
|
97
|
+
end
|
98
|
+
|
99
|
+
def key(*fields)
|
100
|
+
@local_parameters = fields
|
101
|
+
|
102
|
+
@local_parameters.flatten!
|
103
|
+
@local_parameters.compact!
|
104
|
+
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
# Defines a new data type for Blendris:Model construction.
|
109
|
+
def type(name, klass)
|
110
|
+
(class << self; self; end).instance_eval do
|
111
|
+
define_method name do |varname, options|
|
112
|
+
options ||= {}
|
113
|
+
options[:type] = klass
|
114
|
+
redis_symbols[varname.to_s] = options
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Variables stored in the Redis database.
|
120
|
+
def redis_symbols
|
121
|
+
@redis_symbols ||= {}
|
122
|
+
end
|
123
|
+
|
124
|
+
# Parameters used when creating a new copy of this model.
|
125
|
+
def local_parameters
|
126
|
+
@local_parameters ||= []
|
127
|
+
end
|
128
|
+
|
129
|
+
# Take a value and attempt to make it fit the given field.
|
130
|
+
def cast_value(symbol, value)
|
131
|
+
options = redis_symbols[symbol.to_s]
|
132
|
+
raise ArgumentError.new("#{self.name} is missing its #{symbol}") unless options
|
133
|
+
|
134
|
+
options[:type].cast_to_redis value, options
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|