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 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 table.const_get( :StandardMethods )
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 = self.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.table.columns.keys.each do | key |
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 = table.column_order.index( column.to_sym )
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 = table.column_order.index( column.to_sym )
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
@@ -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
- if options[:columns]
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
@@ -1,22 +1,18 @@
1
1
 
2
2
  class TestDatatype < Test::Unit::TestCase
3
3
 
4
- DATATYPES = Momomoto::Datatype.constants.map do | t |
5
- Momomoto::Datatype.const_get( t )
6
- end
4
+ Momomoto::Datatype.constants.each do | type_name |
5
+ type = Momomoto::Datatype.const_get( type_name )
7
6
 
8
- def test_default
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
- def test_not_null
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
- def test_compile_rule
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
- def test_compile_rule_null
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
- def test_operator_sign
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
- def test_escape
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=>[:person_id,:first_name],:limit=>1})[0]
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.nick_name
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
7
- date: 2007-10-07 00:00:00 +02:00
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