tokyocafe 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,61 @@
1
+ = tokyocafe
2
+
3
+ == DESCRIPTION:
4
+
5
+ TokyoCafe is a set of classes to help you talk
6
+ to TokyoCabinet ( http://1978th.net/tokyocabinet/ ) with Ruby
7
+
8
+ == SYNOPSIS:
9
+
10
+ require 'tokyocafe'
11
+
12
+ class MyClassTest
13
+ include TokyoCafe::Persistable
14
+ database 'db.tct'
15
+ add_timestamp_for :on_create, :on_update
16
+
17
+ attr_accessor :name
18
+
19
+ def before_delete
20
+ puts self.to_h.inspect
21
+ end
22
+ end
23
+
24
+ * See test/test_tokyocafe.rb for more info
25
+
26
+ == REQUIREMENTS:
27
+
28
+ * libtokyocabinet-ruby, '>= 1.21'
29
+
30
+ == INSTALL:
31
+
32
+ gem install tokyocafe
33
+
34
+ == CREDITS:
35
+
36
+ * Grately inspired from http://couchobject.rubyforge.org/
37
+
38
+ == LICENSE:
39
+
40
+ (The MIT License)
41
+
42
+ Copyright (c) 2009 spk
43
+
44
+ Permission is hereby granted, free of charge, to any person obtaining
45
+ a copy of this software and associated documentation files (the
46
+ 'Software'), to deal in the Software without restriction, including
47
+ without limitation the rights to use, copy, modify, merge, publish,
48
+ distribute, sublicense, and/or sell copies of the Software, and to
49
+ permit persons to whom the Software is furnished to do so, subject to
50
+ the following conditions:
51
+
52
+ The above copyright notice and this permission notice shall be
53
+ included in all copies or substantial portions of the Software.
54
+
55
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
56
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
57
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
58
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
59
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
60
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
61
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,75 @@
1
+ require 'rake/testtask'
2
+ require 'rake/packagetask'
3
+ require 'rake/rdoctask'
4
+ require 'rake'
5
+ require 'find'
6
+
7
+ # Globals
8
+
9
+ PKG_NAME = 'tokyocafe'
10
+ PKG_VERSION = '0.0.2'
11
+
12
+ PKG_FILES = ['README.rdoc', 'Rakefile']
13
+ Find.find('lib/', 'test/') do |f|
14
+ if FileTest.directory?(f) and f =~ /\.svn|\.git/
15
+ Find.prune
16
+ else
17
+ PKG_FILES << f
18
+ end
19
+ end
20
+
21
+ # Tasks
22
+
23
+ task :default => [:clean, :repackage]
24
+
25
+ Rake::TestTask.new do |t|
26
+ t.libs << "test"
27
+ t.test_files = FileList['test/test_*.rb']
28
+ end
29
+
30
+ Rake::RDocTask.new do |rd|
31
+ f = []
32
+ require 'find'
33
+ Find.find('lib/') do |file|
34
+ # Skip hidden files (.svn/ directories and Vim swapfiles)
35
+ if file.split(/\//).last =~ /^\./
36
+ Find.prune
37
+ else
38
+ f << file if not FileTest.directory?(file)
39
+ end
40
+ end
41
+ rd.rdoc_files.include(f)
42
+ rd.options << '--all'
43
+ end
44
+
45
+ Rake::PackageTask.new(PKG_NAME, PKG_VERSION) do |p|
46
+ p.need_tar = true
47
+ p.package_files = PKG_FILES
48
+ end
49
+
50
+ # "Gem" part of the Rakefile
51
+ require 'rake/gempackagetask'
52
+
53
+ spec = Gem::Specification.new do |s|
54
+ s.author = 'spk'
55
+ s.email = 'spk@tuxfamily.org'
56
+ s.platform = Gem::Platform::RUBY
57
+ s.homepage = 'http://github.com/spk/tokyocafe'
58
+ s.summary = <<-DESC.strip.gsub(/\n\s+/, " ")
59
+ TokyoCafe is a set of classes to help you talk to TokyoCabinet
60
+ DESC
61
+ s.name = PKG_NAME
62
+ s.version = PKG_VERSION
63
+ s.requirements << 'libtokyocabinet-ruby'
64
+ s.require_path = 'lib'
65
+ s.files = PKG_FILES
66
+ s.description = <<-DESC.strip.gsub(/\n\s+/, " ")
67
+ TokyoCafe is a set of classes to help you talk
68
+ to TokyoCabinet (http://1978th.net/tokyocabinet/) with Ruby
69
+ DESC
70
+ end
71
+
72
+ Rake::GemPackageTask.new(spec) do |pkg|
73
+ pkg.need_zip = true
74
+ pkg.need_tar = true
75
+ end
data/lib/tokyocafe.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'tokyocabinet'
2
+
3
+ require 'tokyocafe/persistable'
4
+ require 'tokyocafe/version'
5
+
6
+ module TokyoCafe
7
+ end
@@ -0,0 +1,218 @@
1
+ require 'tokyocafe/persistable/meta_classes'
2
+
3
+ module TokyoCafe
4
+ module Persistable
5
+ # this method will be added to the class as an instance method
6
+
7
+ include TokyoCabinet
8
+ attr_accessor :id, :created_at, :updated_at
9
+
10
+ @@tdb = TDB::new
11
+
12
+ def initialize(args={})
13
+ args.keys.each { |name| instance_variable_set "@" + name.to_s, args[name] }
14
+ end
15
+
16
+ def new?
17
+ self.id.nil?
18
+ end
19
+
20
+ def save(db_uri = location)
21
+ perform_callback(:before_save)
22
+ tokyo_open
23
+ @location = db_uri
24
+ if new?
25
+ performed = tokyo_create
26
+ else
27
+ performed = tokyo_update
28
+ end
29
+ tokyo_close
30
+ perform_callback(:after_save)
31
+ performed
32
+ end
33
+
34
+ def delete
35
+ performed = false
36
+ unless new?
37
+ perform_callback(:before_delete)
38
+ tokyo_open
39
+ performed = @@tdb.out(self.id)
40
+ tokyo_close
41
+ perform_callback(:after_delete)
42
+ end
43
+ performed
44
+ end
45
+ alias destroy delete
46
+
47
+ def to_s
48
+ self.id
49
+ end
50
+
51
+ def to_h
52
+ parameters = {}
53
+ parameters['class'] = self.class.to_s
54
+
55
+ if RUBY_VERSION.to_f > 1.8
56
+ excluded_instance_variables = [:@location, :@created_at,
57
+ :@updated_at]
58
+ else
59
+ excluded_instance_variables = ['@location', '@created_at',
60
+ '@updated_at']
61
+ end
62
+ instance_variables = self.instance_variables - excluded_instance_variables
63
+ instance_variables.each do |k|
64
+ key = k[1..-1]
65
+ value = self.instance_variable_get(k)
66
+ parameters[key] = value
67
+ end
68
+
69
+ if self.class::tokyo_cafe_timestamp_on_update?
70
+ parameters['updated_at'] = Time.now.to_s
71
+ end
72
+
73
+ unless new?
74
+ # update
75
+ parameters['id'] = id
76
+ if self.class::tokyo_cafe_timestamp_on_create?
77
+ parameters['created_at'] = created_at
78
+ end
79
+ else
80
+ # create
81
+ if self.class::tokyo_cafe_timestamp_on_create?
82
+ parameters['created_at'] = Time.now.to_s
83
+ end
84
+ end
85
+ parameters
86
+ end
87
+
88
+ def to_json
89
+ parameters = self.to_h
90
+ begin
91
+ parameters.to_json
92
+ rescue JSON::GeneratorError
93
+ TokyoCafe::Utils::decode_strings(parameters).to_json
94
+ end
95
+ end
96
+
97
+ protected
98
+ def tokyo_open
99
+ unless @@tdb.open(location, TDB::OWRITER | TDB::OCREAT)
100
+ ecode = @@tdb.ecode
101
+ STDERR.printf("open error: %s\n", @@tdb.errmsg(ecode))
102
+ end
103
+ end
104
+
105
+ def tokyo_close
106
+ @@tdb.close
107
+ end
108
+
109
+ def tokyo_create
110
+ perform_callback(:before_create)
111
+
112
+ hash_value = self.to_h
113
+
114
+ pkey = @@tdb.genuid
115
+ doc_hash = hash_value.merge({'id' => pkey})
116
+
117
+ if @@tdb.put(pkey, doc_hash)
118
+ @id = pkey
119
+ if self.class::tokyo_cafe_timestamp_on_create?
120
+ @created_at = Time.now.to_s
121
+ end
122
+ performed = true
123
+ else
124
+ ecode = @@tdb.ecode
125
+ STDERR.printf("put error: %s\n", @@tdb.errmsg(ecode))
126
+ performed = false
127
+ end
128
+ perform_callback(:after_create)
129
+ performed
130
+ end
131
+
132
+ def tokyo_update
133
+ perform_callback(:before_update)
134
+ if self.class::tokyo_cafe_timestamp_on_update?
135
+ @updated_at = Time.now.to_s
136
+ end
137
+
138
+ doc_value = self.to_h
139
+ if @@tdb.put(id, doc_value)
140
+ @id = id
141
+ if self.class::tokyo_cafe_timestamp_on_create?
142
+ @created_at = created_at
143
+ end
144
+ performed = true
145
+ else
146
+ ecode = @@tdb.ecode
147
+ STDERR.printf("put error: %s\n", @@tdb.errmsg(ecode))
148
+ performed = false
149
+ end
150
+ perform_callback(:after_update)
151
+ performed
152
+ end
153
+
154
+ #
155
+ # Performs callbacks before and after these events:
156
+ # * create
157
+ # * update
158
+ # * save
159
+ # * delete
160
+ #
161
+ def perform_callback(the_callback)
162
+ self.send(the_callback) if self.respond_to?(the_callback)
163
+ end
164
+
165
+ module ClassMethods
166
+ # this method will be added to the class as a class method
167
+ include TokyoCabinet
168
+
169
+ def get_by_id(id, db_uri = self.location)
170
+ @@tdb = TDB::new
171
+ unless @@tdb.open(db_uri, TDB::OREADER)
172
+ ecode = @@tdb.ecode
173
+ STDERR.printf("open error: %s\n", @@tdb.errmsg(ecode))
174
+ end
175
+ if id && @@tdb.get(id)
176
+ h = @@tdb.get(id)
177
+ res = self.new(h)
178
+ else
179
+ res = nil
180
+ end
181
+ @@tdb.close
182
+ return res
183
+ end
184
+ alias get get_by_id
185
+
186
+ # :conditions => {:name => 'tokyo'}, :limit => 3, :order => { :name => :ASC }
187
+ def search(options = {}, db_uri = self.location)
188
+ @@tdb = TDB::new
189
+ unless @@tdb.open(db_uri, TDB::OREADER)
190
+ ecode = @@tdb.ecode
191
+ STDERR.printf("open error: %s\n", @@tdb.errmsg(ecode))
192
+ end
193
+ qry = TDBQRY::new(@@tdb)
194
+ if options.include?(:conditions)
195
+ options[:conditions].each do |k,v|
196
+ qry.addcond(k.to_s, TDBQRY::QCSTREQ, v.to_s)
197
+ end
198
+ end
199
+ if options.include?(:limit) && options[:limit].to_i > 0
200
+ qry.setlimit(options[:limit])
201
+ end
202
+ if options.include?(:order)
203
+ options[:order].each do |k,v|
204
+ qry.setorder(k.to_s, TDBQRY.const_get("QOSTR#{v.to_s.upcase}"))
205
+ end
206
+ end
207
+ res = qry.search
208
+ @@tdb.close
209
+ return res
210
+ end
211
+
212
+ def set_location=(db_uri)
213
+ @location = db_uri == "" ? nil : db_uri
214
+ end
215
+
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,80 @@
1
+ module TokyoCafe
2
+ module Persistable
3
+ def self.included(klass)
4
+ klass.extend(TokyoCafe::Persistable::ClassMethods)
5
+
6
+ klass.class_eval do
7
+
8
+ ##
9
+ # Timestamps
10
+ ##
11
+
12
+ # Timestamps are false by default
13
+ def self.tokyo_cafe_timestamp_on_update?; false; end
14
+ def self.tokyo_cafe_timestamp_on_create?; false; end
15
+
16
+ #
17
+ # Adds timestamps to the class.
18
+ #
19
+ # Example:
20
+ #
21
+ # class Vacation
22
+ # include TokyoCafe::Persistable
23
+ # add_timestamp_for :on_create, :on_update
24
+ # end
25
+ #
26
+ # my_vacation = Vacation.new
27
+ # my_vacation.save(db_address)
28
+ # my_vacation.created_at => Somedate
29
+ # my_vacation.updated_at => Somedate
30
+ #
31
+ def self.add_timestamp_for(*timestamp_actions)
32
+ timestamp_actions.each do |action|
33
+ case action
34
+ when :on_create
35
+ self.class_eval do
36
+ def self.tokyo_cafe_timestamp_on_create?; true; end
37
+ end
38
+ when :on_update
39
+ self.class_eval do
40
+ def self.tokyo_cafe_timestamp_on_update?; true; end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # Location methods are added both as instance methods and
47
+ # as class level methods. The class level methods are needed
48
+ # when loading new objects from the database and the instance
49
+ # methods are used throughout the class
50
+ def self.location; @tokyo_cafe_class_storage_location ||= nil; end
51
+ def location; @location; end
52
+ alias storage_location location
53
+
54
+ #
55
+ # Sets the location of the database to use by default
56
+ #
57
+ # Example:
58
+ #
59
+ # class AppleTree
60
+ # include TokyoCafe::Persistable
61
+ # database 'db/db.tct'
62
+ # end
63
+ #
64
+ # apple_tree = AppleTree.new
65
+ # apple_tree.save # saves automatically to the predefined
66
+ # # database location
67
+ #
68
+ def self.database(db_uri)
69
+ @tokyo_cafe_class_storage_location = db_uri
70
+ self.instance_eval do
71
+ define_method("location") do
72
+ @location ||= db_uri
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,9 @@
1
+ module TokyoCafe #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 2
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ require 'test/unit'
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'tokyocafe'
5
+
6
+ class MyClassTest
7
+ include TokyoCafe::Persistable
8
+ database 'db.tct'
9
+ add_timestamp_for :on_create, :on_update
10
+
11
+ attr_accessor :name
12
+
13
+ def after_save
14
+ puts self.inspect
15
+ puts self.to_h.inspect
16
+ end
17
+
18
+ def before_delete
19
+ puts self.to_h.inspect
20
+ end
21
+ end
22
+
23
+ class TokyoCafeTest < Test::Unit::TestCase
24
+
25
+ def default_test
26
+ save_test
27
+ get_test
28
+ search_test
29
+ delete_test
30
+ end
31
+
32
+ def save_test
33
+ t = MyClassTest.new
34
+ t.name = 'tokyo'
35
+ assert t.new?
36
+ assert t.save
37
+ t.id
38
+ end
39
+
40
+ def get_test
41
+ id = save_test
42
+ a = MyClassTest.get(id)
43
+ assert !a.new?
44
+ a.name = 'tokyooo'
45
+ assert a.save
46
+ a.id
47
+ end
48
+
49
+ def delete_test
50
+ id = get_test
51
+ b = MyClassTest.get(id)
52
+ assert b.delete
53
+ end
54
+
55
+ def search_test
56
+ t = MyClassTest.new
57
+ t.name = 'tokyo'
58
+ t.save
59
+ res = MyClassTest.search(:conditions => {:name => "tokyo"}, :limit => 3, :order => {:name => :ASC})
60
+ assert !res.empty?
61
+ assert (res.size < 4)
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tokyocafe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - spk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-11 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: TokyoCafe is a set of classes to help you talk to TokyoCabinet (http://1978th.net/tokyocabinet/) with Ruby
17
+ email: spk@tuxfamily.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - lib/tokyocafe/version.rb
28
+ - lib/tokyocafe/persistable.rb
29
+ - lib/tokyocafe/persistable/meta_classes.rb
30
+ - lib/tokyocafe.rb
31
+ - test/test_tokyocafe.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/spk/tokyocafe
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements:
54
+ - libtokyocabinet-ruby
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: TokyoCafe is a set of classes to help you talk to TokyoCabinet
60
+ test_files: []
61
+