rhubarb 0.3.0 → 0.4.0

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/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