tokyocafe 0.0.2

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.
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
+