momomoto 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|