activetokyocabinet 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -80,7 +80,7 @@ see http://gemcutter.org/gems/activetokyocabinet
80
80
  # - Include `ID' in search condition
81
81
  # see http://activetokyocabi.rubyforge.org/svn/trunk/lib/active_tokyocabinet/sqlparser.y
82
82
 
83
- == Expanded operator
83
+ === Expanded operator
84
84
 
85
85
  # see http://1978th.net/tokyotyrant/rubydoc/classes/TokyoTyrant/RDBQRY.html
86
86
 
@@ -125,7 +125,7 @@ see http://gemcutter.org/gems/activetokyocabinet
125
125
  emp = Emp.find(:all, :conditions => ['ename ftsex ?', 'MIKU || RIN'])
126
126
  emp = Emp.find(:all, :conditions => ['ename ftsex ?', 'HATSUNE && MIKU'])
127
127
 
128
- == Low layer API
128
+ === Low layer API
129
129
 
130
130
  Emp.tdbopen do |tdb|
131
131
  pkey = tdb.genuid
@@ -138,11 +138,39 @@ see http://gemcutter.org/gems/activetokyocabinet
138
138
  end
139
139
  # proc method return empty array.
140
140
 
141
- == Set index
141
+ === Set index
142
142
 
143
143
  # see http://1978th.net/tokyotyrant/rubydoc/classes/TokyoTyrant/RDBTBL.html#M000007
144
144
 
145
145
  Emp.setindex(:age, :decimal)
146
146
 
147
+ == Example
148
+ === database.yml
149
+
150
+ # TokyoCabinet
151
+ development:
152
+ adapter: tokyocabinet
153
+ database: db/casket/
154
+ # save to `$RAILS_ROOT/db/casket/*.tct'.
155
+
156
+ # TokyoTyrant
157
+ development:
158
+ adapter: tokyotyrant
159
+ database:
160
+ emps: { host: localhost, port: 1978 }
161
+ depts: { host: localhost, port: 1979 }
162
+
163
+ == Schema free
164
+
165
+ class Book < ActiveRecord::Base
166
+ include ActiveTokyoCabinet::TDB
167
+ schema_free :timestamp => true
168
+ end
169
+
170
+ Book.create(:title => 'photo book', :author => 'Tanaka Takeshi', :price => 200)
171
+ Book.create(:title => 'note book', :price => 50)
172
+
173
+ books = Book.find(:all, :conditions => ['author = ?', 'Tanaka Takeshi'])
174
+
147
175
  == Related article
148
176
  * http://d.hatena.ne.jp/winebarrel/20100106/p1
@@ -44,9 +44,9 @@ def scan
44
44
  yield :NUMBER, tok.to_i
45
45
  elsif (tok = @ss.scan /[,\(\)\*]/)
46
46
  yield tok, tok
47
- elsif (tok = @ss.scan /(?:[a-z_][\w]+\.)*ID\b/i)
47
+ elsif (tok = @ss.scan /(?:[a-z_]\w+\.|[a-z]\.)*ID\b/i)
48
48
  yield :ID, tok
49
- elsif (tok = @ss.scan /(?:[a-z_][\w]+\.)*[a-z_][\w]+/i)
49
+ elsif (tok = @ss.scan /(?:[a-z_]\w+\.|[a-z]\.)*(?:[a-z_]\w+|[a-z])/i)
50
50
  yield :IDENTIFIER, tok
51
51
  else
52
52
  raise Racc::ParseError, ('parse error on value "%s"' % @ss.rest.inspect)
@@ -232,9 +232,9 @@ def scan
232
232
  yield :NUMBER, tok.to_i
233
233
  elsif (tok = @ss.scan /[,\(\)\*]/)
234
234
  yield tok, tok
235
- elsif (tok = @ss.scan /(?:[a-z_][\w]+\.)*ID\b/i)
235
+ elsif (tok = @ss.scan /(?:[a-z_]\w+\.|[a-z]\.)*ID\b/i)
236
236
  yield :ID, tok
237
- elsif (tok = @ss.scan /(?:[a-z_][\w]+\.)*[a-z_][\w]+/i)
237
+ elsif (tok = @ss.scan /(?:[a-z_]\w+\.|[a-z]\.)*(?:[a-z_]\w+|[a-z])/i)
238
238
  yield :IDENTIFIER, tok
239
239
  else
240
240
  raise Racc::ParseError, ('parse error on value "%s"' % @ss.rest.inspect)
@@ -1,9 +1,89 @@
1
1
  module ActiveTokyoCabinet
2
2
  module TDB
3
3
  def self.included(mod)
4
+ mod.instance_eval %{
5
+ def schema_free(options = {})
6
+ raise 'invalid definition: schema is already defined' if @__schema_defined
7
+ @__schema_free_defined = true
8
+
9
+ primary_key = ActiveRecord::ConnectionAdapters::Column.new('id', nil)
10
+ primary_key.primary = true
11
+ @columns = [primary_key]
12
+
13
+ class_eval <<-EOS
14
+ @@__with_timestamp = \#{options[:timestamp].inspect}
15
+
16
+ alias :__respond_to? :respond_to?
17
+
18
+ def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
19
+ quoted = {}
20
+ connection = self.class.connection
21
+
22
+ __attributes = (attributes || {}).merge(@__attributes || {})
23
+ __attributes.delete('id')
24
+
25
+ if @@__with_timestamp == :on
26
+ %w(created_at updated_at).each {|i| __attributes.delete(i) }
27
+ elsif @@__with_timestamp
28
+ %w(created_on updated_on).each {|i| __attributes.delete(i) }
29
+ else
30
+ %w(created_on updated_on created_at updated_at).each do |i|
31
+ __attributes.delete(i)
32
+ end
33
+ end
34
+
35
+ __attributes.each do |name, value|
36
+ quoted[name] = connection.quote(value)
37
+ end
38
+
39
+ quoted
40
+ end
41
+
42
+ def respond_to?(name, priv = false); true; end
43
+
44
+ def method_missing(name, *args, &block)
45
+ @__attributes ||= {}
46
+ name = name.to_s
47
+
48
+ if __respond_to?(name)
49
+ super
50
+ elsif name =~ /\\\\A(.+)=\\\\Z/ and args.length == 1
51
+ @__attributes[$1] = args[0]
52
+ elsif name =~ /[^=]\\\\Z/ and args.length == 0
53
+ @__attributes[$1]
54
+ else
55
+ raise NoMethodError, "undefined method `\\\#{name}' for \#{name}"
56
+ super
57
+ end
58
+ end
59
+ EOS
60
+ end
61
+ }
62
+
63
+ mod.instance_eval %{
64
+ def tdbopen(readonly = false)
65
+ self.connection.tdbopen(self.table_name, readonly) {|tdb| yield(tdb) }
66
+ end
67
+
68
+ def setindex(name, type)
69
+ self.connection.setindex(self.table_name, name, type)
70
+ end
71
+
72
+ def proc(*args, &block)
73
+ if block and (options = args.last) and options.kind_of?(Hash)
74
+ options[:activetokyocabinet_proc] = block
75
+ end
76
+
77
+ self.find(*args)
78
+ end
79
+ }
80
+
4
81
  {:string => :to_s, :int => :to_i, :float => :to_f}.each do |type, conv|
5
82
  mod.instance_eval %{
6
83
  def #{type}(name)
84
+ raise 'invalid definition: schema_free is already defined' if @__schema_free_defined
85
+ @__schema_defined = true
86
+
7
87
  unless @columns
8
88
  primary_key = ActiveRecord::ConnectionAdapters::Column.new('id', nil)
9
89
  primary_key.primary = true
@@ -13,22 +93,6 @@ module ActiveTokyoCabinet
13
93
  @columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, nil)
14
94
  class_eval "def \#{name}; v = self[:\#{name}]; (v.nil? || v.empty?) ? nil : v.#{conv}; end"
15
95
  end
16
-
17
- def tdbopen(readonly = false)
18
- self.connection.tdbopen(self.table_name, readonly) {|tdb| yield(tdb) }
19
- end
20
-
21
- def setindex(name, type)
22
- self.connection.setindex(self.table_name, name, type)
23
- end
24
-
25
- def proc(*args, &block)
26
- if block and (options = args.last) and options.kind_of?(Hash)
27
- options[:activetokyocabinet_proc] = block
28
- end
29
-
30
- self.find(*args)
31
- end
32
96
  }
33
97
  end
34
98
  end
@@ -0,0 +1,4 @@
1
+ class Book < ActiveRecord::Base
2
+ include ActiveTokyoCabinet::TDB
3
+ schema_free
4
+ end
@@ -8,6 +8,7 @@ require 'active_record'
8
8
  require 'active_tokyocabinet/tdb'
9
9
  require "#{$wd}/models/employee"
10
10
  require "#{$wd}/models/department"
11
+ require "#{$wd}/models/book"
11
12
 
12
13
  ActiveRecord::Base.logger = Logger.new($stderr)
13
14
  ActiveRecord::Base.logger.level = Logger::INFO
@@ -188,6 +189,7 @@ module ActiveTokyoCabinetSpec
188
189
  def clean
189
190
  FileUtils.rm_f "#{$wd}/employees.tct"
190
191
  FileUtils.rm_f "#{$wd}/departments.tct"
192
+ FileUtils.rm_f "#{$wd}/books.tct"
191
193
  end
192
194
  end # class << self
193
195
  end # module TokyoCabinetSpec
@@ -202,6 +204,7 @@ module ActiveTokyoCabinetSpec
202
204
  :database => {
203
205
  :employees => {:host => 'localhost', :port => 1978},
204
206
  :departments => {:host => 'localhost', :port => 1979},
207
+ :books => {:host => 'localhost', :port => 1980},
205
208
  }
206
209
  )
207
210
  end
@@ -213,6 +216,7 @@ module ActiveTokyoCabinetSpec
213
216
 
214
217
  `ttserver -port 1978 -dmn -pid "#{$wd}/employees.pid" "#{$wd}/employees.tct"`
215
218
  `ttserver -port 1979 -dmn -pid "#{$wd}/departments.pid" "#{$wd}/departments.tct"`
219
+ `ttserver -port 1980 -dmn -pid "#{$wd}/books.pid" "#{$wd}/books.tct"`
216
220
  sleep 3
217
221
  end
218
222
 
@@ -507,6 +507,75 @@ describe 'tokyocabinet:' do
507
507
  Department.count.should == 0
508
508
  end
509
509
 
510
+ it "schema free" do
511
+ Book.create(:foo => 'bar', :zoo => 'baz', :n => 100)
512
+ Book.create!(:hoge => 'fuga', :n => 200)
513
+
514
+ book = Book.new
515
+ book.xxx = 'XXX'
516
+ book.yyy = 'YYY'
517
+ book.zzz = 'ZZZ'
518
+ book.n = 300
519
+ book.save!
520
+
521
+ Book.count.should == 3
522
+
523
+ book = Book.find(2)
524
+ book.foo.should be_nil
525
+ book.hoge.should == 'fuga'
526
+ book.n.should == '200'
527
+
528
+ book.n = 250
529
+ book.save
530
+
531
+ books = Book.find(:all, :conditions => ['hoge = ?', 'fuga'])
532
+ books.length.should == 1
533
+ books[0].xxx.should be_nil
534
+ books[0].hoge.should == 'fuga'
535
+ books[0].n.should == '250'
536
+
537
+ books = Book.find(:all, :conditions => ['n >= ?', 200])
538
+ books.length.should == 2
539
+ books = books.sort_by {|i| i.id }
540
+
541
+ books[0].id.should == 2
542
+ books[0].hoge.should == 'fuga'
543
+ books[0].n.should == '250'
544
+
545
+ books[1].id.should == 3
546
+ books[1].xxx.should == 'XXX'
547
+ books[1].yyy.should == 'YYY'
548
+ books[1].zzz.should == 'ZZZ'
549
+ books[1].n.should == '300'
550
+
551
+ Book.update_all("xxx = 'xxx'", ['n > ?', 100])
552
+
553
+ books = Book.find(:all)
554
+ books.length.should == 3
555
+ books = books.sort_by {|i| i.id }
556
+
557
+ books[0].id.should == 1
558
+ books[0].xxx.should be_nil
559
+
560
+ books[1].id.should == 2
561
+ books[1].xxx.should == 'xxx'
562
+
563
+ books[2].id.should == 3
564
+ books[2].xxx.should == 'xxx'
565
+
566
+ Book.find(2).destroy
567
+
568
+ books = Book.find(:all)
569
+ books.length.should == 2
570
+ books = books.sort_by {|i| i.id }
571
+
572
+ books[0].id.should == 1
573
+ books[1].id.should == 3
574
+
575
+ Book.delete_all
576
+ Book.count.should == 0
577
+ end
578
+
510
579
  after do
511
580
  TokyoCabinetSpec.clean
512
581
  end
@@ -507,6 +507,75 @@ describe 'tokyotyrant:' do
507
507
  Department.count.should == 0
508
508
  end
509
509
 
510
+ it "schema free" do
511
+ Book.create(:foo => 'bar', :zoo => 'baz', :n => 100)
512
+ Book.create!(:hoge => 'fuga', :n => 200)
513
+
514
+ book = Book.new
515
+ book.xxx = 'XXX'
516
+ book.yyy = 'YYY'
517
+ book.zzz = 'ZZZ'
518
+ book.n = 300
519
+ book.save!
520
+
521
+ Book.count.should == 3
522
+
523
+ book = Book.find(2)
524
+ book.foo.should be_nil
525
+ book.hoge.should == 'fuga'
526
+ book.n.should == '200'
527
+
528
+ book.n = 250
529
+ book.save
530
+
531
+ books = Book.find(:all, :conditions => ['hoge = ?', 'fuga'])
532
+ books.length.should == 1
533
+ books[0].xxx.should be_nil
534
+ books[0].hoge.should == 'fuga'
535
+ books[0].n.should == '250'
536
+
537
+ books = Book.find(:all, :conditions => ['n >= ?', 200])
538
+ books.length.should == 2
539
+ books = books.sort_by {|i| i.id }
540
+
541
+ books[0].id.should == 2
542
+ books[0].hoge.should == 'fuga'
543
+ books[0].n.should == '250'
544
+
545
+ books[1].id.should == 3
546
+ books[1].xxx.should == 'XXX'
547
+ books[1].yyy.should == 'YYY'
548
+ books[1].zzz.should == 'ZZZ'
549
+ books[1].n.should == '300'
550
+
551
+ Book.update_all("xxx = 'xxx'", ['n > ?', 100])
552
+
553
+ books = Book.find(:all)
554
+ books.length.should == 3
555
+ books = books.sort_by {|i| i.id }
556
+
557
+ books[0].id.should == 1
558
+ books[0].xxx.should be_nil
559
+
560
+ books[1].id.should == 2
561
+ books[1].xxx.should == 'xxx'
562
+
563
+ books[2].id.should == 3
564
+ books[2].xxx.should == 'xxx'
565
+
566
+ Book.find(2).destroy
567
+
568
+ books = Book.find(:all)
569
+ books.length.should == 2
570
+ books = books.sort_by {|i| i.id }
571
+
572
+ books[0].id.should == 1
573
+ books[1].id.should == 3
574
+
575
+ Book.delete_all
576
+ Book.count.should == 0
577
+ end
578
+
510
579
  after do
511
580
  TokyoTyrantSpec.clean
512
581
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activetokyocabinet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - winebarrel
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-27 00:00:00 +09:00
12
+ date: 2010-03-28 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -40,6 +40,7 @@ files:
40
40
  - spec/tokyotyrant_spec.rb
41
41
  - spec/models/department.rb
42
42
  - spec/models/employee.rb
43
+ - spec/models/book.rb
43
44
  - spec/spec_helper.rb
44
45
  - spec/tokyocabinet_spec.rb
45
46
  - spec/tcspec2ttspec.sh