lore 0.4.8 → 0.9.2

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.
Files changed (111) hide show
  1. data/Manifest.txt +16 -7
  2. data/README.rdoc +91 -0
  3. data/benchmark/benchmark.sql +11 -0
  4. data/benchmark/results.txt +28 -0
  5. data/benchmark/select.rb +352 -0
  6. data/lib/lore.rb +22 -8
  7. data/lib/lore/adapters/context.rb +64 -0
  8. data/lib/lore/adapters/postgres-pr.rb +6 -0
  9. data/lib/lore/adapters/postgres-pr/connection.rb +93 -0
  10. data/lib/lore/adapters/postgres-pr/result.rb +63 -0
  11. data/lib/lore/{types.rb → adapters/postgres-pr/types.rb} +36 -0
  12. data/lib/lore/adapters/postgres.rb +24 -0
  13. data/lib/lore/adapters/postgres/connection.rb +81 -0
  14. data/lib/lore/adapters/postgres/result.rb +82 -0
  15. data/lib/lore/adapters/postgres/types.rb +91 -0
  16. data/lib/lore/bits.rb +18 -0
  17. data/lib/lore/cache/abstract_entity_cache.rb +2 -1
  18. data/lib/lore/cache/cacheable.rb +12 -177
  19. data/lib/lore/cache/memcache_entity_cache.rb +89 -0
  20. data/lib/lore/cache/memory_entity_cache.rb +77 -0
  21. data/lib/lore/cache/mmap_entity_cache.rb +2 -2
  22. data/lib/lore/cache/mmap_entity_cache_bork.rb +86 -0
  23. data/lib/lore/clause.rb +107 -35
  24. data/lib/lore/{exception → exceptions}/ambiguous_attribute.rb +2 -2
  25. data/lib/lore/{exception → exceptions}/cache_exception.rb +1 -1
  26. data/lib/lore/exceptions/database_exception.rb +16 -0
  27. data/lib/lore/{exception/invalid_parameter.rb → exceptions/invalid_field.rb} +7 -4
  28. data/lib/lore/exceptions/unknown_type.rb +18 -0
  29. data/lib/lore/exceptions/validation_failure.rb +71 -0
  30. data/lib/lore/gui/form_generator.rb +109 -60
  31. data/lib/lore/gui/lore_model_select_field.rb +1 -0
  32. data/lib/lore/migration.rb +84 -25
  33. data/lib/lore/model.rb +3 -18
  34. data/lib/lore/{aspect.rb → model/aspect.rb} +0 -0
  35. data/lib/lore/model/associations.rb +225 -0
  36. data/lib/lore/model/attribute_settings.rb +233 -0
  37. data/lib/lore/model/filters.rb +34 -0
  38. data/lib/lore/model/mockable.rb +62 -0
  39. data/lib/lore/{model_factory.rb → model/model_factory.rb} +68 -39
  40. data/lib/lore/model/model_instance.rb +382 -0
  41. data/lib/lore/{model_shortcuts.rb → model/model_shortcuts.rb} +7 -0
  42. data/lib/lore/model/polymorphic.rb +53 -0
  43. data/lib/lore/model/prepare.rb +97 -0
  44. data/lib/lore/model/table_accessor.rb +1016 -0
  45. data/lib/lore/query.rb +71 -0
  46. data/lib/lore/query_shortcuts.rb +43 -11
  47. data/lib/lore/strategies/table_delete.rb +115 -0
  48. data/lib/lore/strategies/table_insert.rb +146 -0
  49. data/lib/lore/strategies/table_select.rb +299 -0
  50. data/lib/lore/strategies/table_update.rb +155 -0
  51. data/lib/lore/validation/parameter_validator.rb +85 -26
  52. data/lib/lore/validation/type_validator.rb +34 -78
  53. data/{custom_models.rb → lore-0.9.2.gem} +0 -0
  54. data/lore.gemspec +26 -17
  55. data/spec/clause.rb +37 -0
  56. data/spec/fixtures/blank_models.rb +37 -0
  57. data/{test/model.rb → spec/fixtures/models.rb} +64 -41
  58. data/spec/fixtures/polymorphic_models.rb +68 -0
  59. data/spec/model_associations.rb +86 -0
  60. data/spec/model_create.rb +47 -0
  61. data/spec/model_definition.rb +151 -0
  62. data/spec/model_delete.rb +31 -0
  63. data/spec/model_inheritance.rb +50 -0
  64. data/spec/model_polymorphic.rb +85 -0
  65. data/spec/model_select.rb +101 -0
  66. data/spec/model_select_eager.rb +42 -0
  67. data/spec/model_union_select.rb +33 -0
  68. data/spec/model_update.rb +45 -0
  69. data/spec/model_validation.rb +20 -0
  70. data/spec/spec_db.sql +808 -0
  71. data/spec/spec_env.rb +19 -0
  72. data/spec/spec_helpers.rb +77 -0
  73. metadata +93 -82
  74. data/lib/lore/README.txt +0 -84
  75. data/lib/lore/behaviours/lockable.rb +0 -55
  76. data/lib/lore/behaviours/movable.rb +0 -72
  77. data/lib/lore/behaviours/paginated.rb +0 -31
  78. data/lib/lore/behaviours/versioned.rb +0 -36
  79. data/lib/lore/connection.rb +0 -152
  80. data/lib/lore/exception/invalid_klass_parameters.rb +0 -63
  81. data/lib/lore/exception/unknown_typecode.rb +0 -19
  82. data/lib/lore/result.rb +0 -119
  83. data/lib/lore/symbol.rb +0 -58
  84. data/lib/lore/table_accessor.rb +0 -1790
  85. data/lib/lore/table_deleter.rb +0 -116
  86. data/lib/lore/table_inserter.rb +0 -170
  87. data/lib/lore/table_instance.rb +0 -389
  88. data/lib/lore/table_selector.rb +0 -285
  89. data/lib/lore/table_updater.rb +0 -157
  90. data/lib/lore/validation.rb +0 -65
  91. data/lib/lore/validation/message.rb +0 -60
  92. data/lib/lore/validation/reason.rb +0 -52
  93. data/lore_test.log +0 -2366
  94. data/test/README +0 -31
  95. data/test/custom_models.rb +0 -18
  96. data/test/env.rb +0 -5
  97. data/test/prepare.rb +0 -37
  98. data/test/tc_aspect.rb +0 -58
  99. data/test/tc_cache.rb +0 -83
  100. data/test/tc_clause.rb +0 -104
  101. data/test/tc_deep_inheritance.rb +0 -49
  102. data/test/tc_factory.rb +0 -57
  103. data/test/tc_filter.rb +0 -37
  104. data/test/tc_form.rb +0 -32
  105. data/test/tc_model.rb +0 -140
  106. data/test/tc_prepare.rb +0 -44
  107. data/test/tc_refined_query.rb +0 -88
  108. data/test/tc_table_accessor.rb +0 -267
  109. data/test/tc_thread.rb +0 -100
  110. data/test/test_db.sql +0 -400
  111. data/test/test_lore.rb +0 -50
@@ -1,11 +1,11 @@
1
1
 
2
2
  module Lore
3
- module Exception
3
+ module Exceptions
4
4
 
5
5
  class Ambiguous_Attribute < ::Exception
6
6
 
7
7
  def initialize(table_a, table_b, attribute)
8
- @message = 'Ambiguous attribute: '+attribute+ ' exists in '+table_a+' and '+table_b+'. '
8
+ @message = "Ambiguous attribute: #{attribute.inspect} exists in #{table_a} and #{table_b}. "
9
9
  end
10
10
 
11
11
  end # class
@@ -2,7 +2,7 @@
2
2
  require('lore/cache/bits')
3
3
 
4
4
  module Lore
5
- module Cache
5
+ module Exceptions
6
6
 
7
7
  class Cache_Read_Exception < ::Exception
8
8
 
@@ -0,0 +1,16 @@
1
+
2
+ module Lore
3
+ module Exceptions
4
+
5
+ class Database_Exception < ::Exception
6
+
7
+ attr_reader :message
8
+
9
+ def initialize(msg)
10
+ @message = msg
11
+ end
12
+
13
+ end
14
+
15
+ end # module Exception
16
+ end # module Lore
@@ -1,8 +1,8 @@
1
1
 
2
2
  module Lore
3
- module Exception
3
+ module Exceptions
4
4
 
5
- class Invalid_Parameters < ::Exception
5
+ class Invalid_Field < ::Exception
6
6
 
7
7
  attr_reader :invalid_params, :reason
8
8
 
@@ -19,17 +19,20 @@ module Exception
19
19
  }
20
20
  result
21
21
  end
22
+ def inspect
23
+ serialize.inspect
24
+ end
22
25
 
23
26
  end
24
27
 
25
- class Invalid_Types < Invalid_Parameters
28
+ class Invalid_Types < Invalid_Field
26
29
  def initialize(invalid_params)
27
30
  super(invalid_params)
28
31
  @reason = :type
29
32
  end
30
33
  end
31
34
 
32
- class Unmet_Constraints < Invalid_Parameters
35
+ class Unmet_Constraints < Invalid_Field
33
36
  def initialize(invalid_params)
34
37
  super(invalid_params)
35
38
  @reason = :constraint
@@ -0,0 +1,18 @@
1
+
2
+ module Lore
3
+ module Exceptions
4
+
5
+ class Unknown_Type < ::Exception
6
+
7
+ attr_reader :code, :value
8
+
9
+ def initialize(type_code, value)
10
+ @code = type_code
11
+ @value = value
12
+ @message = "Unknown database type: #{type_code.to_s} for value #{value.inspect}"
13
+ end
14
+
15
+ end
16
+
17
+ end # module
18
+ end # module
@@ -0,0 +1,71 @@
1
+
2
+ require('lore/exceptions/invalid_field')
3
+
4
+ module Lore
5
+ module Exceptions
6
+
7
+ # A validation failure consists of one or more Invalid_Field
8
+ # instances for every model field for which invalid values have
9
+ # been passed, e.g. on Model.create or Model.update.
10
+ #
11
+ # Usage:
12
+ #
13
+ # raise Validation_Failure.new(The_Model, {
14
+ # # Generic error. Example: :user_id => Lore.integer
15
+ # :table_foo => Invalid_Field.new( :the_attribute => :error_type )
16
+ # # Constraint error. Example: :email => :format
17
+ # :table bar => Unmet_Constraints.new( :the_attribute => :error_type )
18
+ # # Type error. Example: :user_id => Lore.integer or :user_id => :missing
19
+ # :table_batz => Invalid_Types.new( :the_attribute => :error_type )
20
+ # })
21
+ #
22
+ class Validation_Failure < ::Exception
23
+
24
+ # Instances of Exception::Invalid_Field
25
+ attr_reader :invalid_fields
26
+ # Model klass that failed validation
27
+ attr_reader :invalid_klass
28
+
29
+ def initialize(klass, invalid_params_hash)
30
+ # Instances of Exception::Invalid_Field
31
+ @invalid_fields = invalid_params_hash
32
+ @invalid_klass = klass
33
+ @message = "#{self.class.to_s}: #{@invalid_fields.inspect}"
34
+ log()
35
+ end
36
+
37
+ def log()
38
+ # {{{
39
+ Lore.logger.error { "====== VALIDATION FAILURE ===========" }
40
+ Lore.logger.error { "Invalid field values for klass #{@invalid_klass}: " }
41
+ Lore.logger.error { 'Invalid field values are: ' }
42
+ @invalid_fields.each_pair { |table, ip|
43
+ Lore.logger.error { " |- Table: #{table}: #{ip.inspect}" }
44
+ }
45
+ Lore.logger.error { 'Required attributes are: ' }
46
+ @invalid_klass.__attributes__.required.each_pair { |table, ip|
47
+ Lore.logger.error { " |- Table: #{table}: #{ip.inspect}" }
48
+ }
49
+ end # }}}
50
+
51
+ def serialize()
52
+ # {{{
53
+ serials = {}
54
+ @invalid_fields.each_pair { |table, invalid_param|
55
+ serials[table] = invalid_param.serialize
56
+ }
57
+ return serials
58
+ end # def }}}
59
+
60
+ def inspect()
61
+ "Model(#{@invalid_klass}) => #{@invalid_fields.serialize} " <<
62
+ "Required: #{@invalid_klass.__attributes__.required.inspect}"
63
+ end
64
+ alias explain serialize
65
+
66
+ end
67
+
68
+
69
+ end # module
70
+ end # module
71
+
@@ -1,7 +1,8 @@
1
1
 
2
- require('aurita')
3
- Aurita.import_module :gui, :module
4
- Aurita.import_module :gui, :model_select_field
2
+ require('rubygems')
3
+ require('aurita-gui')
4
+ require('lore')
5
+ require('lore/gui/lore_model_select_field')
5
6
 
6
7
  module Lore
7
8
  module GUI
@@ -17,9 +18,10 @@ module GUI
17
18
  # puts generator.form
18
19
  #
19
20
  class Form_Generator
21
+ include Aurita::GUI
20
22
 
21
23
  attr_reader :form, :klass
22
- attr_accessor :custom_elements, :labels, :params
24
+ attr_accessor :custom_elements, :labels, :params, :form_class
23
25
 
24
26
  def initialize(klass=nil)
25
27
  @klass = klass
@@ -27,6 +29,7 @@ module GUI
27
29
  @params = {}
28
30
  @custom_elements = {}
29
31
  @form = false
32
+ @form_class = Aurita::GUI::Form
30
33
  end
31
34
 
32
35
  def form
@@ -34,83 +37,129 @@ module GUI
34
37
  @form
35
38
  end
36
39
 
40
+ @@type_field_map = {
41
+ :default => Proc.new { |l,f| Input_Field.new(:label => l, :name => f) },
42
+ Lore::PG_BOOL => Proc.new { |l,f| Boolean_Field.new(:label => l, :name => f) },
43
+ Lore::PG_VARCHAR => Proc.new { |l,f| Input_Field.new(:label => l, :name => f) },
44
+ Lore::PG_SMALLINT => Proc.new { |l,f| Input_Field.new(:label => l, :name => f) },
45
+ Lore::PG_INT => Proc.new { |l,f| Input_Field.new(:label => l, :name => f) },
46
+ Lore::PG_TEXT => Proc.new { |l,f| Textarea_Field.new(:label => l, :name => f) },
47
+
48
+ Lore::PG_TIMESTAMP_TIMEZONE => Proc.new { |l,f| Datetime_Field.new(:label => l, :name => f,
49
+ :date_format => 'dmy',
50
+ :time_format => 'hms',
51
+ :year_range => (2009..2020)) },
52
+
53
+ Lore::PG_TIMESTAMP => Proc.new { |l,f| Datetime_Field.new(:label => l, :name => f,
54
+ :date_format => 'dmy',
55
+ :time_format => 'hms',
56
+ :year_range => (2009..2020)) },
57
+
58
+ Lore::PG_DATE => Proc.new { |l,f| Date_Field.new(:label => l, :name => f,
59
+ :date_format => 'dmy',
60
+ :year_range => (2009..2020)) },
61
+
62
+ Lore::PG_TIME => Proc.new { |l,f| Time_Field.new(:label => l, :name => f,
63
+ :time_format => 'hm') }
64
+ }
65
+
66
+ protected
67
+
68
+ def field_for(type, params)
69
+ element = @@type_field_map[type]
70
+ element ||= @@type_field_map[:default]
71
+ return element.call(params[:label], params[:name])
72
+ end
73
+
74
+ public
75
+
37
76
  def generate
38
- @form = Aurita::GUI::Form.new(@params)
77
+ @form = @form_class.new(@params)
78
+ model_labels = @klass.attribute_labels if @klass.respond_to?(:attribute_labels)
79
+ model_labels ||= {}
80
+
81
+ @klass.get_fields.each_pair { |table, attributes|
39
82
 
40
- @klass.get_attributes.each_pair { |table, attributes|
41
83
  attributes.each { |attribute|
42
- label_tag = table.gsub('.','--') << '--' << attribute
84
+ label_tag = "#{table.gsub('.','--')}--#{attribute}"
43
85
  label = @labels[label_tag]
44
- label ||= label_tag
45
- full_attrib = table + '.' << attribute
46
- field_name = full_attrib.gsub('.','_')
86
+ label = attribute.to_s.capitalize if label.to_s == ''
87
+
88
+ full_attrib = "#{table}.#{attribute}"
89
+ field_name = full_attrib
47
90
  form_element = false
91
+
92
+ attributes = @klass.__attributes__
93
+ associations = @klass.__associations__
94
+
95
+ constraints = attributes.constraints
96
+ constraints = constraints[table] if constraints
97
+ constraints = constraints[attribute] if constraints
98
+
99
+ aggregate_klasses = associations.aggregate_klasses
100
+ has_a_klasses = associations.has_a
101
+ implicits = attributes.implicit
102
+ ecplicits = attributes.explicit
103
+ requireds = attributes.required
104
+ primary_keys = attributes.primary_keys
105
+ attribute_types = attributes.types
48
106
 
49
- # @custom_elements is a hash mapping attribute names to
50
- # Custom_Element instances.
107
+ # @custom_elements is a hash mapping attribute
108
+ # names to Custom_Element instances.
51
109
  if ((@custom_elements[table]) and
52
110
  (@custom_elements[table][attribute])) then
53
111
 
54
- form_element = @custom_elements[table][attribute].new(table, attribute, label)
112
+ form_element = @custom_elements[table][attribute].new(:label => label,
113
+ :id => full_attrib,
114
+ :name => field_name)
55
115
 
56
- elsif (@klass.get_primary_keys[table].nil? or # Ignore primary key attributes
57
- !@klass.get_primary_keys[table].include? attribute) and
58
- (@klass.get_implicit_attributes[table].nil? or # Ignore implicit attributes
59
- !@klass.get_implicit_attributes[table].include? attribute) and
60
- (@klass.get_has_a_klasses.nil? or # Ignore attributes aggregated via has_a associations (added later)
61
- @klass.get_has_a_klasses[table+'.'+attribute].nil?) and
62
- (@klass.get_hidden_attributes[table].nil? or # Ignore otherwise hidden attributes
63
- !@klass.get_hidden_attributes[table].include? attribute)
116
+ elsif (primary_keys[table].nil? or # Ignore primary key attributes
117
+ !primary_keys[table].include? attribute) and
118
+ (implicits[table].nil? or # Ignore implicit attributes
119
+ !implicits[table].include? attribute) and
120
+ (has_a_klasses.nil? or # Ignore attributes aggregated via has_a associations (added later)
121
+ has_a_klasses[full_attrib].nil?)
122
+ # and (hidden_attributes[table].nil? or # Ignore otherwise hidden attributes
123
+ # !hidden_attributes[table].include? attribute)
64
124
  then
65
- # Attribute has to be added to form, according to data type
66
- case @klass.get_attribute_types[table][attribute]
67
- when Lore::PG_BOOL
68
- form_element = Radio_Field.new(:label => label,
69
- :name => field_name,
70
- :options => { 't' => 'yes', 'f' => 'no' } )
71
-
72
- when Lore::PG_SMALLINT || Lore::PG_INT
73
- form_element = Input_Field.new(:label => label, :name => field_name)
74
- when Lore::PG_VARCHAR
75
- form_element = Input_Field.new(:label => label, :name => field_name)
76
- when Lore::PG_TEXT
77
- form_element = Textarea_Field.new(:label => label, :name => field_name)
78
- when Lore::PG_TIMESTAMP_TIMEZONE
79
- form_element = Datetime_Field.new(:label => label, :name => field_name, :date_format => 'dmy', :time_format => 'hms', :year_range => (2009..2020))
80
- when Lore::PG_DATE
81
- form_element = Date_Field.new(:label => label, :name => field_name, :date_format => 'dmy', :year_range => (2009..2020))
82
- else
83
- form_element = Input_Field.new(:label => label, :name => field_name)
84
- end
85
-
86
- elsif (!@klass.get_has_a_klasses.nil? and
87
- !@klass.get_has_a_klasses[full_attrib].nil?)
125
+ form_element = field_for(attribute_types[table][attribute], :name => field_name, :label => label)
126
+ elsif (!has_a_klasses.nil? and
127
+ !has_a_klasses[full_attrib].nil?)
88
128
  then
89
- foreign_klass = @klass.get_has_a_klasses[full_attrib]
90
- form_element = Model_Select_Field.new(foreign_klass, :label => label, :name => field_name)
129
+ foreign_klass = has_a_klasses[full_attrib]
130
+ form_element = Aurita::GUI::Lore_Model_Select_Field.new(foreign_klass, :label => label, :name => field_name)
91
131
 
92
- elsif (!@klass.get_aggregate_klasses.nil? and
93
- !@klass.get_aggregate_klasses[full_attrib].nil?)
132
+ elsif (!aggregate_klasses.nil? and
133
+ !aggregate_klasses[full_attrib].nil?)
94
134
  then
95
- foreign_klass = @klass.get_aggregate_klasses[full_attrib]
96
- form_element = Model_Select_Field.new(foreign_klass, :label => label, :name => field_name)
135
+ foreign_klass = aggregate_klasses[full_attrib]
136
+ form_element = Aurita::GUI::Lore_Model_Select_Field.new(foreign_klass, :label => label, :name => field_name)
97
137
 
98
- # Attribute is explixit (expected/required) but not
99
- # catched before -> Add attribute as hidden field:
100
- elsif (!@klass.get_explicit_attributes[table].nil? and
101
- @klass.get_explicit_attributes[table].include? attribute)
102
- then
103
- form_element = Hidden_Field.new(:name => field_name)
104
-
105
- elsif (!@klass.get_implicit_attributes[table].nil? and
106
- @klass.get_implicit_attributes[table].include? attribute)
138
+ elsif (!implicits[table].nil? and
139
+ implicits[table].include? attribute)
107
140
  then
108
141
  # Implicit field, ignored
109
142
  end
110
143
 
111
- @form.add(form_element) if form_element
144
+ if form_element then
145
+ form_element.data_type = attribute_types[table][attribute]
146
+ if(!requireds[table].nil? and
147
+ requireds[table].include? attribute) then
148
+ form_element.required!
149
+ end
150
+ if constraints then
151
+ if constraints[:minlength] then
152
+ end
153
+ if constraints[:maxlength] then
154
+ end
155
+ if constraints[:format] then
156
+ end
157
+ end
158
+ @form.add(form_element)
159
+ end
112
160
  }
113
161
  }
162
+ return @form
114
163
  end
115
164
 
116
165
  end # class
@@ -10,6 +10,7 @@ module GUI
10
10
  @model = model
11
11
  @filter = params[:filter]
12
12
  @filter ||= true
13
+ @data_type = Lore::PG_INT
13
14
  if block_given? then
14
15
  @select_block = block
15
16
  else
@@ -1,45 +1,104 @@
1
1
 
2
+ require('lore/types')
3
+ require('lore/model/model_factory')
4
+
2
5
  module Lore
3
6
 
4
7
 
5
8
  # Usage:
6
9
  #
7
- # Using auto-bootstrap of models:
10
+ # class User_Profile_Migration < Lore::Migration
8
11
  #
9
- # class My_Model < Lore::Model
10
- # extend Lore::Migration
11
- #
12
- # table :my_model, :public
13
- # primary_key :key_a, :key_a_seq
14
- # primary_key :key_b
12
+ # def up
13
+ # create_table(:user_profile) {
14
+ # schema :public
15
+ # primary_key :user_profile_id, :user_profile_id_seq
16
+ # index :user_name
17
+ #
18
+ # user_name Lore::Type.varchar(50), :null => false, :unique => true
19
+ # is_admin Lore::Type.boolean, :null => false, :default => false
20
+ # registered Lore::Type.timestamp, :null => false, :default => 'now()'
21
+ # }
22
+ # end
15
23
  #
16
- # has_attributes {
17
- # :foo, Lore::Type.integer, { :unique => true, :default => 1 }
18
- # :bar, Lore::Type.integer, { :not_null => true, :check => 'bar < 1000' }
19
- # }
24
+ # def down
25
+ # drop_table(:user_profile)
26
+ # drop_sequence(:user_profile_id_seq)
27
+ # end
20
28
  #
21
- # def self.up
22
- # bootstrap()
23
- # My_Model.create(:foo => 23, :bar => 123)
24
- # end
29
+ # end
25
30
  #
26
- # end
27
31
  #
28
- module Migration
32
+ class Migration
29
33
 
30
- def has_attributes(attrib_hash)
31
- @model_schema = attrib_hash
34
+ attr_reader :primary_keys, :schema, :table, :fields, :field_params, :indices, :drop_tables
35
+
36
+ def initialize()
37
+ @primary_keys = []
38
+ @sequences = {}
39
+ @fields = []
40
+ @field_params = {}
41
+ @indices = []
42
+ @drop_tables = []
43
+ @drop_sequences = []
44
+ @constraints = []
32
45
  end
33
46
 
34
- def update_schema
35
- @factory = Model_Factory.new(self.class.to_s)
36
- @model_schema.each_pair { |attrib_name, attrib_props|
37
- @factory.add_attribute(attrib_name.to_s, attrib_props)
47
+ def create_table(table_name, schema=:public, &block)
48
+ instance_eval(&block)
49
+ @table = table_name
50
+ factory = Model_Factory.new(table_name)
51
+ @primary_keys.each { |p|
52
+ factory.add_attribute(p, :null => false, :type => Lore::Type.integer)
53
+ factory.add_primary_key(:attribute => p,
54
+ :key_name => "#{table_name}_pkey",
55
+ :sequence => @sequences[p] )
56
+ }
57
+ @fields.each { |f|
58
+ factory.add_attribute(f, @field_params[f])
38
59
  }
60
+ factory.build_table
61
+ end
62
+
63
+ def drop_table(table_name)
64
+ @drop_tables << table_name
65
+ end
66
+ def drop_sequence(sequence_name)
67
+ @drop_sequences << sequence_name
68
+ end
69
+
70
+ def up()
71
+ end
72
+
73
+ def down()
74
+ end
75
+
76
+ def primary_key(key_name, sequence_name=nil)
77
+ key_name = key_name.to_sym
78
+ @primary_keys << key_name
79
+ @sequences[key_name] = sequence_name.to_sym if sequence_name
80
+ end
81
+
82
+ def schema(schema_name)
83
+ @schema = schema_name
84
+ end
85
+
86
+ def add_field(field_name, type, params={})
87
+ @fields << field_name
88
+ @field_params[field_name] = params
89
+ @field_params[field_name][:type] = type
90
+ end
91
+
92
+ def add_constraint(constraint)
93
+ @constraints << constraint
94
+ end
95
+
96
+ def index(field_name)
97
+ @indices << field_name
39
98
  end
40
99
 
41
- def bootstrap
42
- @factory.build_table
100
+ def method_missing(field_name, type, params={})
101
+ add_field(field_name, type, params)
43
102
  end
44
103
 
45
104
  end