rhubarb 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -13,10 +13,19 @@
13
13
  require 'rhubarb/mixins/freshness'
14
14
 
15
15
  module Rhubarb
16
+ # Forward declaration
17
+ module Persistence; end
18
+
16
19
  # Methods mixed in to the class object of a persisting class
17
- module PersistingClassMixins
18
- PCM_INPUT_TRANSFORMERS = {:blob=>Util.blobify_proc, :zblob=>Util.zblobify_proc, :object=>Util.swizzle_object_proc}
19
- PCM_OUTPUT_TRANSFORMERS = {:object=>Util.deswizzle_object_proc, :zblob=>Util.dezblobify_proc, }
20
+ module PersistingClassMixins
21
+ if ::Rhubarb::Persistence::sqlite_13
22
+ PCM_INPUT_TRANSFORMERS = {:blob=>Util.blobify_proc, :zblob=>Util.zblobify_proc, :object=>Util.swizzle_object_proc, :boolean=>Util.truthify_proc}
23
+ PCM_OUTPUT_TRANSFORMERS = {:object=>Util.deswizzle_object_proc, :zblob=>Util.dezblobify_proc, :string=>Proc.new {|v| v.to_s}}
24
+ else
25
+ PCM_INPUT_TRANSFORMERS = {:blob=>Util.blobify_proc, :zblob=>Util.zblobify_proc, :object=>Util.swizzle_object_proc}
26
+ PCM_OUTPUT_TRANSFORMERS = {:object=>Util.deswizzle_object_proc, :zblob=>Util.dezblobify_proc}
27
+ end
28
+
20
29
  # Returns the name of the database table modeled by this class.
21
30
  # Defaults to the name of the class (sans module names)
22
31
  def table_name(quoted=false)
@@ -56,16 +65,38 @@ module Rhubarb
56
65
 
57
66
  alias find_by_id find
58
67
 
59
- def find_by(arg_hash)
68
+ def find_by_sqlite13(arg_hash)
60
69
  results = []
61
70
  arg_hash = arg_hash.dup
62
71
  valid_cols = self.colnames.intersection arg_hash.keys
63
72
  select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
64
- arg_hash.each {|key,val| arg_hash[key] = val.row_id if val.respond_to? :row_id}
73
+ arg_hash.each do |key,val|
74
+ arg_hash[key] = val.row_id if val.respond_to? :row_id
75
+ xform = PCM_INPUT_TRANSFORMERS[colkinds[key]]
76
+ arg_hash[key] = xform.call(val) if xform
77
+ end
78
+ db.do_query("select * from #{quoted_table_name} where #{select_criteria} order by row_id", arg_hash) {|tup| results << self.new(tup) }
79
+ results
80
+ end
81
+
82
+ def find_by_sqlite12(arg_hash)
83
+ results = []
84
+ arg_hash = arg_hash.dup
85
+ valid_cols = self.colnames.intersection arg_hash.keys
86
+ select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
87
+ arg_hash.each do |key,val|
88
+ arg_hash[key] = val.row_id if val.respond_to? :row_id
89
+ end
65
90
  db.do_query("select * from #{quoted_table_name} where #{select_criteria} order by row_id", arg_hash) {|tup| results << self.new(tup) }
66
91
  results
67
92
  end
68
93
 
94
+ if ::Rhubarb::Persistence::sqlite_13
95
+ alias find_by find_by_sqlite13
96
+ else
97
+ alias find_by find_by_sqlite12
98
+ end
99
+
69
100
  # Does what it says on the tin. Since this will allocate an object for each row, it isn't recomended for huge tables.
70
101
  def find_all
71
102
  results = []
@@ -147,16 +178,32 @@ module Rhubarb
147
178
  # add a find for this column (a class method)
148
179
  klass = (class << self; self end)
149
180
  klass.class_eval do
150
- define_method find_method_name do |arg|
151
- results = []
152
- db.do_query(find_query, arg) {|row| results << self.new(row)}
153
- results
154
- end
155
-
156
- define_method find_first_method_name do |arg|
157
- result = nil
158
- db.do_query(find_query, arg) {|row| result = self.new(row) ; break }
159
- result
181
+ if ::Rhubarb::Persistence::sqlite_13
182
+ define_method find_method_name do |arg|
183
+ results = []
184
+ arg = Util.rhubarb_fk_identity(arg)
185
+ db.do_query(find_query, arg) {|row| results << self.new(row)}
186
+ results
187
+ end
188
+
189
+ define_method find_first_method_name do |arg|
190
+ result = nil
191
+ arg = Util.rhubarb_fk_identity(arg)
192
+ db.do_query(find_query, arg) {|row| result = self.new(row) ; break }
193
+ result
194
+ end
195
+ else
196
+ define_method find_method_name do |arg|
197
+ results = []
198
+ db.do_query(find_query, arg) {|row| results << self.new(row)}
199
+ results
200
+ end
201
+
202
+ define_method find_first_method_name do |arg|
203
+ result = nil
204
+ db.do_query(find_query, arg) {|row| result = self.new(row) ; break }
205
+ result
206
+ end
160
207
  end
161
208
  end
162
209
 
@@ -51,7 +51,7 @@ module Rhubarb
51
51
  end
52
52
  end
53
53
 
54
- if @use_prepared_stmts
54
+ if @use_prepared_stmts && Rhubarb::Persistence::prepared_ok
55
55
  class << db
56
56
  include UsePreparedStatements
57
57
  end
@@ -65,6 +65,15 @@ module Rhubarb
65
65
 
66
66
  @dbs = DbCollection.new
67
67
 
68
+ def self.prepared_ok
69
+ !!sqlite_13
70
+ end
71
+
72
+ def self.sqlite_13
73
+ result = SQLite3.constants.include?("VERSION") && SQLite3::VERSION =~ /1\.3\.[0-9]+/
74
+ !!result
75
+ end
76
+
68
77
  def self.open(filename, which=:default, usePrepared=true)
69
78
  dbs.use_prepared_stmts = usePrepared
70
79
  dbs[which] = SQLite3::Database.new(filename)
@@ -91,4 +100,4 @@ module Rhubarb
91
100
  @dbs
92
101
  end
93
102
  end
94
- end
103
+ end
@@ -55,6 +55,11 @@ module Rhubarb
55
55
  @backed = true
56
56
  @tuple = tup
57
57
  mark_fresh
58
+
59
+ unless @tuple.is_a?(Hash)
60
+ @tuple = Hash[*self.class.columns.map{|c| c.name}.zip(tup).flatten]
61
+ end
62
+
58
63
  @row_id = @tuple["row_id"]
59
64
  @created = @tuple["created"]
60
65
  @updated = @tuple["updated"]
@@ -24,7 +24,11 @@ module Rhubarb
24
24
 
25
25
  # Identity for objects that may be used as foreign keys
26
26
  def self.rhubarb_fk_identity(object)
27
- (object.row_id if object.class.ancestors.include? Persisting) || object
27
+ (object.class.ancestors.include?(Persisting) || object.class.ancestors.include?(Rhubarb::Persisting)) ? object.row_id : object
28
+ end
29
+
30
+ def self.truthify_proc
31
+ @truthify_proc ||= Proc.new {|obj| !!(obj) ? "true" : "false"}
28
32
  end
29
33
 
30
34
  def self.blobify_proc
@@ -37,8 +41,11 @@ module Rhubarb
37
41
 
38
42
  def self.dezblobify_proc
39
43
  @dezblobify_proc ||= Proc.new do |obj|
40
- return nil if obj.nil? || obj == ""
41
- Zlib::Inflate.inflate(obj)
44
+ if obj.nil? || obj == ""
45
+ nil
46
+ else
47
+ Zlib::Inflate.inflate(obj)
48
+ end
42
49
  end
43
50
  end
44
51
 
@@ -51,11 +58,13 @@ module Rhubarb
51
58
 
52
59
  def self.deswizzle_object_proc
53
60
  @deswizzle_object_proc ||= Proc.new do |zy_obj|
54
- return nil if zy_obj.nil? || zy_obj == ""
55
-
56
- obj = YAML.load(Zlib::Inflate.inflate(zy_obj))
57
- obj.freeze
61
+ if zy_obj.nil? || zy_obj == ""
62
+ nil
63
+ else
64
+ obj = YAML.load(Zlib::Inflate.inflate(zy_obj))
65
+ obj.freeze
66
+ end
58
67
  end
59
68
  end
60
69
  end
61
- end
70
+ end
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rhubarb}
8
+ s.version = "0.4.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["William Benton"]
12
+ s.date = %q{2011-07-06}
13
+ s.description = %q{Rhubarb is a simple object-graph persistence library implemented as a mixin. It also works with the SPQR library for straightforward object publishing over QMF.}
14
+ s.email = %q{willb@redhat.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc",
18
+ "TODO"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "CHANGES",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "TODO",
27
+ "VERSION",
28
+ "lib/rhubarb/classmixins.rb",
29
+ "lib/rhubarb/column.rb",
30
+ "lib/rhubarb/mixins/freshness.rb",
31
+ "lib/rhubarb/persistence.rb",
32
+ "lib/rhubarb/persisting.rb",
33
+ "lib/rhubarb/reference.rb",
34
+ "lib/rhubarb/rhubarb.rb",
35
+ "lib/rhubarb/util.rb",
36
+ "rhubarb.gemspec",
37
+ "ruby-rhubarb.spec.in",
38
+ "test/helper.rb",
39
+ "test/test_rhubarb.rb"
40
+ ]
41
+ s.homepage = %q{http://git.fedorahosted.org/git/grid/rhubarb.git}
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.7}
44
+ s.summary = %q{Rhubarb: object graph persistence, easy as pie}
45
+ s.test_files = [
46
+ "test/helper.rb",
47
+ "test/test_rhubarb.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
56
+ s.add_runtime_dependency(%q<sqlite3-ruby>, [">= 1.2.2"])
57
+ else
58
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
59
+ s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.2"])
60
+ end
61
+ else
62
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
63
+ s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.2"])
64
+ end
65
+ end
66
+
@@ -1,5 +1,5 @@
1
1
  %{!?ruby_sitelib: %global ruby_sitelib %(ruby -rrbconfig -e 'puts Config::CONFIG["sitelibdir"] ')}
2
- %define rel 1
2
+ %define rel 3
3
3
 
4
4
  Summary: Simple versioned object-graph persistence layer
5
5
  Name: ruby-rhubarb
@@ -29,8 +29,8 @@ instances of specially-declared Ruby classes in a SQLite3 database
29
29
  rm -rf %{buildroot}
30
30
  mkdir -p %{buildroot}/%{ruby_sitelib}/rhubarb
31
31
  mkdir -p %{buildroot}/%{ruby_sitelib}/rhubarb/mixins
32
- cp -f lib/rhubarb/mixins/*.rb %{buildroot}/%{ruby_sitelib}/rhubarb/mixins
33
- cp -f lib/rhubarb/*.rb %{buildroot}/%{ruby_sitelib}/rhubarb
32
+ cp -p -f lib/rhubarb/mixins/*.rb %{buildroot}/%{ruby_sitelib}/rhubarb/mixins
33
+ cp -p -f lib/rhubarb/*.rb %{buildroot}/%{ruby_sitelib}/rhubarb
34
34
 
35
35
  %clean
36
36
  rm -rf %{buildroot}
@@ -48,6 +48,15 @@ rm -rf %{buildroot}
48
48
  %{ruby_sitelib}/rhubarb/persistence.rb
49
49
 
50
50
  %changelog
51
+ * Mon Jun 6 2011 willb <willb@redhat> - 0.3.0-3
52
+ - installation now preserves file modification times
53
+
54
+ * Mon Mar 14 2011 willb <willb@redhat> - 0.3.0-2
55
+ - fix for object output transformers
56
+
57
+ * Tue Feb 15 2011 willb <willb@redhat> - 0.3.0-1
58
+ - fixed bzs 674432, 674433, 677807
59
+
51
60
  * Wed Sep 15 2010 willb <willb@redhat> - 0.2.7-1
52
61
  - Updated to version 0.2.7
53
62
  - fixed problems with hash-valued params in custom queries
@@ -15,7 +15,16 @@ require 'helper'
15
15
  require 'fileutils'
16
16
 
17
17
  Customer = Struct.new(:name, :address)
18
+ SQLITE_13 = ::Rhubarb::Persistence::sqlite_13
19
+ CONSTRAINT_EXCEPTION = SQLITE_13 ? SQLite3::ConstraintException : SQLite3::SQLException
18
20
 
21
+ BFB_MAX = 512
22
+
23
+ class ParityTest
24
+ include Rhubarb::Persisting
25
+ declare_column :number, :integer
26
+ declare_column :parity, :boolean
27
+ end
19
28
 
20
29
  class TestClass
21
30
  include Rhubarb::Persisting
@@ -138,13 +147,13 @@ class Order
138
147
  declare_column :group, :int
139
148
  end
140
149
 
141
- class PreparedStmtBackendTests < Test::Unit::TestCase
150
+ class NoPreparedStmtBackendTests < Test::Unit::TestCase
142
151
  def dbfile
143
152
  ENV['RHUBARB_TEST_DB'] || ":memory:"
144
153
  end
145
154
 
146
155
  def use_prepared
147
- true
156
+ false
148
157
  end
149
158
 
150
159
  def setup
@@ -168,7 +177,7 @@ class PreparedStmtBackendTests < Test::Unit::TestCase
168
177
  klasses << ObjectTestTable
169
178
  klasses << RhubarbNamespace::NMTC
170
179
  klasses << RhubarbNamespace::NMTC2
171
-
180
+ klasses << ParityTest
172
181
  klasses.each { |klass| klass.create_table }
173
182
 
174
183
  @flist = []
@@ -178,6 +187,34 @@ class PreparedStmtBackendTests < Test::Unit::TestCase
178
187
  Rhubarb::Persistence::close()
179
188
  end
180
189
 
190
+ def test_boolean_find_by
191
+ # believe me, I chuckled while writing this
192
+ bit_parity = Proc.new do |k|
193
+ k.to_s(2).split("0").join.size.even?
194
+ end
195
+
196
+ expected_numbers = Set.new
197
+
198
+ BFB_MAX.times do |i|
199
+ ParityTest.create(:number=>i, :parity=>bit_parity.call(i))
200
+ expected_numbers << i
201
+ end
202
+
203
+ even = ParityTest.find_by(:parity=>true)
204
+ odd = ParityTest.find_by(:parity=>false)
205
+
206
+ assert_equal(BFB_MAX, even.size+odd.size)
207
+ {even=>true, odd=>false}.each do |collection, par|
208
+ collection.each do |pt|
209
+ assert_equal(bit_parity.call(pt.number), pt.parity)
210
+ assert_equal(par, pt.parity)
211
+ expected_numbers.delete(pt.number)
212
+ end
213
+ end
214
+
215
+ assert_equal(0, expected_numbers.size)
216
+ end
217
+
181
218
  def test_reserved_word_table
182
219
  assert_nothing_raised do
183
220
  Create.create_table
@@ -514,9 +551,9 @@ class PreparedStmtBackendTests < Test::Unit::TestCase
514
551
 
515
552
  result = TestClass.find_by_foo(2)
516
553
  tc = result[0]
517
- assert(result.size == 1, "TestClass.find_by_foo(2) should return exactly one result")
518
- assert(tc.foo == 2, "tc.foo (found by foo) should have the value 2")
519
- assert(tc.bar == "argh", "tc.bar (found by foo) should have the value \"argh\"")
554
+ assert_equal(1, result.size, "TestClass.find_by_foo(2) should return exactly one result")
555
+ assert_equal(2, tc.foo, "tc.foo (found by foo) should have the value 2")
556
+ assert_equal("argh", tc.bar, "tc.bar (found by foo) should have the value \"argh\"")
520
557
  end
521
558
 
522
559
  def test_create_and_find_first_by_foo
@@ -653,7 +690,7 @@ class PreparedStmtBackendTests < Test::Unit::TestCase
653
690
  end
654
691
 
655
692
  def test_referential_integrity
656
- assert_raise SQLite3::SQLException do
693
+ assert_raise CONSTRAINT_EXCEPTION do
657
694
  FromRef.create(:t => 42)
658
695
  end
659
696
 
@@ -981,8 +1018,10 @@ class PreparedStmtBackendTests < Test::Unit::TestCase
981
1018
  end
982
1019
  end
983
1020
 
984
- class NoPreparedStmtBackendTests < PreparedStmtBackendTests
985
- def use_prepared
986
- false
1021
+ unless SQLITE_13
1022
+ class PreparedStmtBackendTests < NoPreparedStmtBackendTests
1023
+ def use_prepared
1024
+ true
1025
+ end
987
1026
  end
988
1027
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhubarb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - William Benton
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-15 00:00:00 -06:00
18
+ date: 2011-07-06 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -62,7 +62,6 @@ extra_rdoc_files:
62
62
  - TODO
63
63
  files:
64
64
  - .document
65
- - .gitignore
66
65
  - CHANGES
67
66
  - LICENSE
68
67
  - README.rdoc
@@ -77,6 +76,7 @@ files:
77
76
  - lib/rhubarb/reference.rb
78
77
  - lib/rhubarb/rhubarb.rb
79
78
  - lib/rhubarb/util.rb
79
+ - rhubarb.gemspec
80
80
  - ruby-rhubarb.spec.in
81
81
  - test/helper.rb
82
82
  - test/test_rhubarb.rb
@@ -85,8 +85,8 @@ homepage: http://git.fedorahosted.org/git/grid/rhubarb.git
85
85
  licenses: []
86
86
 
87
87
  post_install_message:
88
- rdoc_options:
89
- - --charset=UTF-8
88
+ rdoc_options: []
89
+
90
90
  require_paths:
91
91
  - lib
92
92
  required_ruby_version: !ruby/object:Gem::Requirement
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC