lib/og/store/kirby.rb in og-0.26.0 vs lib/og/store/kirby.rb in og-0.27.0

- old
+ new

@@ -32,10 +32,16 @@ end end def initialize(options) super + + @typemap = { + :Fixnum => :Integer, + :TrueClass => :Boolean + } + mode = options[:mode] || :local if mode == :client # Use a client/server configuration. @conn = KirbyBase.new(:client, options[:address], options[:port]) @@ -60,14 +66,18 @@ def enchant(klass, manager) klass.send :attr_accessor, :oid klass.send :alias_method, :recno, :oid klass.send :alias_method, :recno=, :oid= + unless klass.properties.include? :recno + klass.property :recno, Fixnum + end + symbols = klass.properties.keys klass.module_eval %{ - def self.kb_create(recno, #{symbols.join(', ')}) + def self.kb_create(#{symbols.join(', ')}) obj = self.allocate obj.recno = recno #{ symbols.map { |s| "obj.#{s} = #{s}; "} } return obj end @@ -156,42 +166,113 @@ def sql_update(sql) # nop, not supported. end + def join(obj1, obj2, table, options = nil) + first, second = join_object_ordering(obj1, obj2) + @conn.get_table(table.to_sym).insert(first.pk, second.pk) + end + + def unjoin(obj1, obj2, table) + first, second = join_object_ordering(obj1, obj2) + + @conn.get_table(table.to_sym).delete do |r| + require 'dev-utils/debug' + breakpoint + r.send(:first_key) == first.pk and + r.send(:second_key) == second.pk + end + end + private + def typemap(key) + @typemap[key] || key + end + def create_table(klass) - fields = fields_for_class(klass) - begin + if @conn.table_exists?(klass.table.to_sym) + get_table(klass).pack # Kirby specific method of database cleanup. + + field_names = field_names_for_class(klass) + actual_fields = get_table(klass).field_names + + field_names.each do |needed_field| + next if actual_fields.include?(needed_field) + + if @options[:evolve_schema] == true + Logger.debug "Adding field '#{needed_field}' to '#{klass.table}'" + field_type = typemap(klass.properties[needed_field].klass.name.to_sym) + if get_table(klass).respond_to?(:add_column) + get_table(klass).add_column(needed_field, field_type) + else + @conn.add_table_column(klass.table, needed_field, field_type) + end + else + Logger.warn "Table '#{klass.table}' is missing field '#{needed_field}' and :evolve_schema is not set to true!" + end + end + + actual_fields.each do |obsolete_field| + next if field_names.include?(obsolete_field) + + if @options[:evolve_schema] == true and @options[:evolve_schema_cautious] == false + Logger.debug "Removing obsolete field '#{obsolete_field}' from '#{klass.table}'" + if get_table(klass).respond_to?(:drop_column) + get_table(klass).drop_column(obsolete_field) + else + @conn.drop_table_column(klass.table, obsolete_field) + end + else + Logger.warn "You have an obsolete field '#{obsolete_field}' on table '#{klass.table}' and :evolve_schema is not set or is in cautious mode!" + end + end + else + Logger.debug "Creating table '#{klass.table}'" + fields = fields_for_class(klass) table = @conn.create_table(klass.table.to_sym, *fields) do |t| t.record_class = klass end - rescue Object => ex - # gmosx: any idea how to better test this? - if ex.to_s =~ /already exists/i - Logger.debug "Table for '#{klass}' already exists!" - return - else - raise + end + +=begin + # Create join tables if needed. Join tables are used in + # 'many_to_many' relations. + + if join_tables = klass.ann.self[:join_tables] + for info in join_tables + unless @conn.table_exists?(info[:table].to_sym) + @conn.create_table(info[:table].to_sym, *create_join_table_sql(info)) + Logger.debug "Created jointable '#{info[:table]}'." + end end end +=end end + + def create_join_table_sql(join_info) + [join_info[:first_key].to_sym, :Integer, join_info[:second_key].to_sym, :Integer] + end + def drop_table(klass) @conn.drop_table(klass.table) if @conn.table_exists?(klass.table) end + def field_names_for_class(klass) + klass.properties.values.map {|p| p.symbol } + end + def fields_for_class(klass) fields = [] klass.properties.values.each do |p| klass.index(p.symbol) if p.index fields << p.symbol - type = p.klass.name.to_sym - type = :Integer if type == :Fixnum + type = typemap(p.klass.name.to_sym) fields << type end return fields