momomoto 0.1.7 → 0.1.8
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/lib/momomoto/base.rb +17 -5
- data/lib/momomoto/row.rb +11 -3
- data/lib/momomoto/table.rb +22 -18
- data/test/test_datatype.rb +8 -20
- data/test/test_row.rb +6 -0
- data/test/test_table.rb +16 -2
- metadata +2 -2
data/lib/momomoto/base.rb
CHANGED
@@ -126,29 +126,41 @@ module Momomoto
|
|
126
126
|
end
|
127
127
|
|
128
128
|
# construct the Row class for the table
|
129
|
-
def initialize_row( row, table )
|
129
|
+
def initialize_row( row, table, columns = table.columns )
|
130
130
|
|
131
131
|
const_set( :Methods, Module.new ) if not const_defined?( :Methods )
|
132
|
-
const_set( :StandardMethods, Module.new ) if not const_defined?( :StandardMethods )
|
132
|
+
row.const_set( :StandardMethods, Module.new ) if not row.const_defined?( :StandardMethods )
|
133
133
|
|
134
134
|
if not row.ancestors.member?( Momomoto::Row )
|
135
135
|
raise CriticalError, "Row is not inherited from Momomoto::Row"
|
136
136
|
end
|
137
137
|
|
138
138
|
row.instance_eval do instance_variable_set( :@table, table ) end
|
139
|
+
row.instance_eval do instance_variable_set( :@columns, columns ) end
|
140
|
+
row.instance_eval do instance_variable_set( :@column_order, columns.keys ) end
|
139
141
|
|
140
|
-
define_row_accessors( const_get( :StandardMethods ), table )
|
142
|
+
define_row_accessors( row.const_get( :StandardMethods ), table, columns )
|
141
143
|
|
142
144
|
row.instance_eval do
|
143
|
-
include
|
145
|
+
include row.const_get( :StandardMethods )
|
144
146
|
include table.const_get( :Methods )
|
145
147
|
end
|
146
148
|
|
149
|
+
if table.columns.keys.length != columns.keys.length
|
150
|
+
unused = table.columns.keys - columns.keys
|
151
|
+
unused.each do | field |
|
152
|
+
row.class_eval do
|
153
|
+
undef_method field if row.instance_methods.member?( "#{field}" )
|
154
|
+
undef_method "#{field}=" if row.instance_methods.member?( "#{field}=" )
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
147
159
|
end
|
148
160
|
|
149
161
|
# defines row setter and getter in the module StandardMethods which
|
150
162
|
# is later included in the Row class
|
151
|
-
def define_row_accessors( method_module, table, columns
|
163
|
+
def define_row_accessors( method_module, table, columns )
|
152
164
|
columns.each_with_index do | ( field_name, data_type ), index |
|
153
165
|
method_module.instance_eval do
|
154
166
|
# define getter for row class
|
data/lib/momomoto/row.rb
CHANGED
@@ -10,6 +10,14 @@ module Momomoto
|
|
10
10
|
@table
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.columns
|
14
|
+
@columns
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.column_order
|
18
|
+
@column_order
|
19
|
+
end
|
20
|
+
|
13
21
|
def []( fieldname )
|
14
22
|
get_column( fieldname )
|
15
23
|
end
|
@@ -66,7 +74,7 @@ module Momomoto
|
|
66
74
|
# convert row to hash
|
67
75
|
def to_hash
|
68
76
|
hash = {}
|
69
|
-
self.class.
|
77
|
+
self.class.columns.keys.each do | key |
|
70
78
|
hash[key] = self[key]
|
71
79
|
end
|
72
80
|
hash
|
@@ -79,7 +87,7 @@ module Momomoto
|
|
79
87
|
raise Error, "Setting primary keys(#{column}) is only allowed for new records"
|
80
88
|
end
|
81
89
|
value = table.columns[column.to_sym].filter_set( value )
|
82
|
-
index =
|
90
|
+
index = self.class.column_order.index( column.to_sym )
|
83
91
|
if !table.columns[column.to_sym].equal( value, @data[index] )
|
84
92
|
mark_dirty( column )
|
85
93
|
@data[index] = value
|
@@ -89,7 +97,7 @@ module Momomoto
|
|
89
97
|
# generic getter for column values
|
90
98
|
def get_column( column )
|
91
99
|
table = self.class.table
|
92
|
-
index =
|
100
|
+
index = self.class.column_order.index( column.to_sym )
|
93
101
|
if table.columns[column.to_sym].respond_to?( :filter_get )
|
94
102
|
table.columns[column.to_sym].filter_get( @data[index] )
|
95
103
|
else
|
data/lib/momomoto/table.rb
CHANGED
@@ -23,7 +23,6 @@ module Momomoto
|
|
23
23
|
# we store the order separate because it's quite important
|
24
24
|
# that it's constant otherwise get_column and set_column
|
25
25
|
# on the row class might stop working
|
26
|
-
@column_order = columns.keys
|
27
26
|
@columns = columns
|
28
27
|
end
|
29
28
|
|
@@ -36,11 +35,6 @@ module Momomoto
|
|
36
35
|
@columns
|
37
36
|
end
|
38
37
|
|
39
|
-
# get the columns of this table
|
40
|
-
def column_order #:nodoc:
|
41
|
-
@column_order
|
42
|
-
end
|
43
|
-
|
44
38
|
def initialize_table # :nodoc:
|
45
39
|
|
46
40
|
@table_name ||= construct_table_name( self.name )
|
@@ -57,6 +51,7 @@ module Momomoto
|
|
57
51
|
|
58
52
|
const_set( :Row, Class.new( Momomoto::Row ) ) if not const_defined?( :Row )
|
59
53
|
initialize_row( const_get( :Row ), self )
|
54
|
+
@row_cache = {}
|
60
55
|
|
61
56
|
# mark class as initialized
|
62
57
|
self.initialized = true
|
@@ -118,16 +113,7 @@ module Momomoto
|
|
118
113
|
# Searches for records and returns an array containing the records
|
119
114
|
def select( conditions = {}, options = {} )
|
120
115
|
initialize_table unless initialized
|
121
|
-
|
122
|
-
row_class = Class.new( Momomoto::Row )
|
123
|
-
cols = {}
|
124
|
-
columns.each do | key, value |
|
125
|
-
cols[key] = value if options[:columns].member?( key )
|
126
|
-
end
|
127
|
-
define_row_accessors( row_class, self, cols )
|
128
|
-
else
|
129
|
-
row_class = const_get(:Row)
|
130
|
-
end
|
116
|
+
row_class = build_row_class( options )
|
131
117
|
sql = compile_select( conditions, options )
|
132
118
|
data = []
|
133
119
|
database.execute( sql ).each do | row |
|
@@ -136,6 +122,25 @@ module Momomoto
|
|
136
122
|
data
|
137
123
|
end
|
138
124
|
|
125
|
+
def build_row_class( options )
|
126
|
+
if options[:columns]
|
127
|
+
options[:columns] += primary_keys
|
128
|
+
options[:columns].uniq!
|
129
|
+
if not @row_cache[options[:columns]]
|
130
|
+
row_class = Class.new( Momomoto::Row )
|
131
|
+
cols = {}
|
132
|
+
columns.each do | key, value |
|
133
|
+
cols[key] = value if options[:columns].member?( key )
|
134
|
+
end
|
135
|
+
initialize_row( row_class, self, cols )
|
136
|
+
@row_cache[options[:columns]] = row_class
|
137
|
+
end
|
138
|
+
return @row_cache[options[:columns]]
|
139
|
+
else
|
140
|
+
return const_get(:Row)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
139
144
|
# Searches for records and returns an array containing the records
|
140
145
|
def select_outer_join( conditions = {}, options = {} )
|
141
146
|
initialize_table unless initialized
|
@@ -236,7 +241,6 @@ module Momomoto
|
|
236
241
|
|
237
242
|
# write row back to database
|
238
243
|
def write( row ) # :nodoc:
|
239
|
-
raise CriticalError unless row.class == const_get(:Row)
|
240
244
|
if row.new_record?
|
241
245
|
insert( row )
|
242
246
|
else
|
@@ -274,7 +278,7 @@ module Momomoto
|
|
274
278
|
def update( row ) # :nodoc:
|
275
279
|
raise CriticalError, 'Updating is only allowed for tables with primary keys' if primary_keys.empty?
|
276
280
|
setter, conditions = [], {}
|
277
|
-
columns.each do | field_name, data_type |
|
281
|
+
row.class.columns.each do | field_name, data_type |
|
278
282
|
next if not row.dirty.member?( field_name )
|
279
283
|
setter << field_name.to_s + ' = ' + data_type.escape(row.get_column(field_name))
|
280
284
|
end
|
data/test/test_datatype.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
|
2
2
|
class TestDatatype < Test::Unit::TestCase
|
3
3
|
|
4
|
-
|
5
|
-
Momomoto::Datatype.const_get(
|
6
|
-
end
|
4
|
+
Momomoto::Datatype.constants.each do | type_name |
|
5
|
+
type = Momomoto::Datatype.const_get( type_name )
|
7
6
|
|
8
|
-
|
9
|
-
DATATYPES.each do | type |
|
7
|
+
define_method( "test_default_#{type_name}" ) do
|
10
8
|
row = Momomoto::Information_schema::Columns.new
|
11
9
|
row.column_default = 'default-value'
|
12
10
|
a = type.new( row )
|
13
11
|
assert_equal( 'default-value', a.default )
|
14
12
|
assert_equal( false, type.new.default )
|
15
13
|
end
|
16
|
-
end
|
17
14
|
|
18
|
-
|
19
|
-
DATATYPES.each do | type |
|
15
|
+
define_method( "test_not_null_#{type_name}" ) do
|
20
16
|
row = Momomoto::Information_schema::Columns.new
|
21
17
|
row.is_nullable = "YES"
|
22
18
|
assert_equal( false, type.new( row ).not_null? )
|
@@ -25,10 +21,8 @@ class TestDatatype < Test::Unit::TestCase
|
|
25
21
|
row.is_nullable = nil
|
26
22
|
assert_equal( false, type.new( row ).not_null? )
|
27
23
|
end
|
28
|
-
end
|
29
24
|
|
30
|
-
|
31
|
-
DATATYPES.each do | type |
|
25
|
+
define_method( "test_compile_rule_#{type_name}" ) do
|
32
26
|
t = type.new
|
33
27
|
tests = [ nil, [], [nil], [nil,nil], {}, {:eq=>nil}, {nil=>nil}]
|
34
28
|
tests.each do | test |
|
@@ -37,18 +31,14 @@ class TestDatatype < Test::Unit::TestCase
|
|
37
31
|
end
|
38
32
|
end
|
39
33
|
end
|
40
|
-
end
|
41
34
|
|
42
|
-
|
43
|
-
DATATYPES.each do | type |
|
35
|
+
define_method( "test_compile_rule_null_#{type_name}" ) do
|
44
36
|
t = type.new
|
45
37
|
assert_equal( "field_name IS NULL", t.compile_rule( :field_name, :NULL) )
|
46
38
|
assert_equal( "field_name IS NOT NULL", t.compile_rule( :field_name, :NOT_NULL) )
|
47
39
|
end
|
48
|
-
end
|
49
40
|
|
50
|
-
|
51
|
-
DATATYPES.each do | type |
|
41
|
+
define_method( "test_operator_sign_#{type_name}" ) do
|
52
42
|
assert_equal( '<=', type.operator_sign( :le ) )
|
53
43
|
assert_equal( '<', type.operator_sign( :lt ) )
|
54
44
|
assert_equal( '>=', type.operator_sign( :ge ) )
|
@@ -57,10 +47,8 @@ class TestDatatype < Test::Unit::TestCase
|
|
57
47
|
assert_equal( '<>', type.operator_sign( :ne ) )
|
58
48
|
assert_raise( Momomoto::CriticalError ) { type.operator_sign( :foo ) }
|
59
49
|
end
|
60
|
-
end
|
61
50
|
|
62
|
-
|
63
|
-
DATATYPES.each do | type |
|
51
|
+
define_method( "test_escape_#{type_name}" ) do
|
64
52
|
t = type.new
|
65
53
|
assert_equal( 'NULL', t.escape( nil ))
|
66
54
|
end
|
data/test/test_row.rb
CHANGED
@@ -56,6 +56,12 @@ class TestRow < Test::Unit::TestCase
|
|
56
56
|
assert( b == a )
|
57
57
|
end
|
58
58
|
|
59
|
+
def test_columns
|
60
|
+
a = Person.new
|
61
|
+
assert_equal( Person.columns, a.class.columns )
|
62
|
+
assert_equal( Person.columns, Person::Row.columns )
|
63
|
+
end
|
64
|
+
|
59
65
|
def test_primary_key_setting
|
60
66
|
a = Person.select_single( nil, {:limit=>1})
|
61
67
|
assert_raise( Momomoto::Error ) do
|
data/test/test_table.rb
CHANGED
@@ -132,14 +132,28 @@ class TestTable < Test::Unit::TestCase
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def test_select_columns
|
135
|
-
p = Person.select({},{:columns=>[:
|
135
|
+
p = Person.select({},{:columns=>[:first_name,:nick_name],:limit=>1})[0]
|
136
136
|
assert( p.respond_to?( :person_id ))
|
137
137
|
assert( p.respond_to?( :first_name ))
|
138
|
+
assert( p.respond_to?( :nick_name ))
|
139
|
+
p.first_name = 'bacon'
|
140
|
+
p.nick_name = 'abc'
|
141
|
+
assert_equal( p.first_name + 'abc', p.nick_name )
|
138
142
|
assert_raise( NoMethodError ) do
|
139
|
-
p.
|
143
|
+
p.last_name
|
140
144
|
end
|
141
145
|
end
|
142
146
|
|
147
|
+
def test_write_columns
|
148
|
+
p = Person.select({},{:columns=>[:first_name],:limit=>1})[0]
|
149
|
+
p.first_name = 'test_write_columns'
|
150
|
+
p.write
|
151
|
+
p2 = Person.select_single(:person_id=>p.person_id)
|
152
|
+
assert_equal( 'test_write_columns', p2.first_name )
|
153
|
+
p2.first_name = 'chunky'
|
154
|
+
p2.write
|
155
|
+
end
|
156
|
+
|
143
157
|
def test_select
|
144
158
|
r = Person.select( nil, {:limit => 3})
|
145
159
|
assert_equal( 3, r.length )
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: momomoto
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-10-
|
6
|
+
version: 0.1.8
|
7
|
+
date: 2007-10-15 00:00:00 +02:00
|
8
8
|
summary: Momomoto is an object relational mapper for PostgreSQL.
|
9
9
|
require_paths:
|
10
10
|
- lib
|