lib/active_groonga/schema.rb in activegroonga-0.0.7 vs lib/active_groonga/schema.rb in activegroonga-1.0.0
- old
+ new
@@ -1,6 +1,6 @@
-# Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
+# Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 2.1 as published by the Free Software Foundation.
#
@@ -11,211 +11,77 @@
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+require 'active_groonga/migrator'
+
module ActiveGroonga
- module Schema
+ class Schema
class << self
- def define(info={}, &block)
- initialize_schema_management_tables
- instance_eval(&block)
-
- unless info[:version].blank?
- assume_migrated_upto_version(info[:version])
- end
+ def define(options={}, &block)
+ new(options).define(&block)
end
- def assume_migrated_upto_version(version)
- version = version.to_i
- table_name = Migrator.groonga_schema_migrations_table_name
-
- migrations_table = Base.context[table_name]
- migrated = migrations_table.records.collect do |record|
- record["version"].to_i
+ def dump(options={})
+ options ||= {}
+ if options.is_a?(Hash)
+ options = options.dup
+ output = options.delete(:output)
+ else
+ output, options = options, {}
end
- versions = Dir['db/migrate/[0-9]*_*.rb'].map do |filename|
- filename.split('/').last.split('_').first.to_i
- end
-
- unless migrated.include?(version)
- migrations_table.add(version.to_s)
- end
-
- inserted = Set.new
- (versions - migrated).each do |v|
- if inserted.include?(v)
- raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict."
- elsif v < version
- migration = migrations_table.add(v.to_s)
- inserted << v
- end
- end
+ new(options).dump(output)
end
+ end
- def initialize_schema_management_tables
- initialize_migrations_table
- end
+ def initialize(options={})
+ @options = (options || {}).dup
+ @version = @options.delete(:version)
+ context = @options.delete(:context) || Base.context
+ @schema = Groonga::Schema.new(:context => context)
+ end
- def create_table(name, options={}, &block)
- table_file = File.join(Base.tables_directory, "#{name}.groonga")
- table_name = Base.groonga_table_name(name)
- options = {:path => table_file}.merge(options)
- options = default_table_options(options).merge(options)
- options = options.merge(:context => Base.context)
- Groonga::Schema.create_table(table_name, options) do |table|
- block.call(TableDefinitionWrapper.new(table))
- end
- end
+ def define(&block)
+ yield(@schema)
+ @schema.define
+ update_version if @version
+ end
- def remove_table(name, options={})
- options = options.merge(:context => Base.context)
- Groonga::Schema.remove_table(name, options)
- end
- alias_method :drop_table, :remove_table
+ def dump(output=nil)
+ dumped_schema = @schema.dump
+ return nil if dumped_schema.nil?
- def add_column(table_name, column_name, type, options={})
- options_with_context = options.merge(:context => Base.context)
- Groonga::Schema.change_table(table_name, options_with_context) do |table|
- table = TableDefinitionWrapper.new(table)
- table.column(column_name, type, options)
- end
+ return_string = false
+ if output.nil?
+ output = StringIO.new
+ return_string = true
end
-
- def remove_column(table_name, *column_names)
- if column_names.last.is_a?(Hash)
- options = columns.pop
+ version = @version || management_table.current_version
+ output << "ActiveGroonga::Schema.define(:version => #{version}) do |schema|\n"
+ output << " schema.instance_eval do\n"
+ dumped_schema.each_line do |line|
+ if /^\s*$/ =~ line
+ output << line
else
- options = {}
+ output << " #{line}"
end
- options_with_context = options.merge(:context => Base.context)
- Groonga::Schema.change_table(table_name, options_with_context) do |table|
- column_names.each do |column_name|
- table.remove_column(column_name)
- end
- end
end
-
- def add_index_column(table_name, target_table_name, target_column_name,
- options={})
- options_for_table = options.reject {|key, value| key == :name}
- options_for_table = options_for_table.merge(:context => Base.context)
- Groonga::Schema.change_table(table_name, options_for_table) do |table|
- table = TableDefinitionWrapper.new(table)
- table.index(target_table_name, target_column_name, options)
- end
+ output << " end\n"
+ output << "end\n"
+ if return_string
+ output.string
+ else
+ output
end
+ end
- private
- def initialize_migrations_table
- table_name = Migrator.schema_migrations_table_name
- groonga_table_name = Migrator.groonga_schema_migrations_table_name
- if Base.context[groonga_table_name].nil?
- table_file = File.join(Base.metadata_directory,
- "#{table_name}.groonga")
- Groonga::Hash.create(:name => groonga_table_name,
- :path => table_file,
- :key_type => "ShortText")
- end
- end
-
- def default_table_options(options)
- default_options = {:sub_records => true}
- case options[:type]
- when :hash, :patricia_trie
- default_options[:default_tokenizer] = "TokenBigram"
- end
- default_options
- end
+ private
+ def management_table
+ @management_table ||= SchemaManagementTable.new
end
- class TableDefinitionWrapper
- def initialize(definition)
- @definition = definition
- end
-
- def column(name, type, options={})
- column_file = File.join(Base.columns_directory(@definition.name),
- "#{name}.groonga")
- options = {:path => column_file}.merge(options)
- @definition.column(name, type, options)
- end
-
- def remove_column(name, options={})
- @definition.remove_column(name, options)
- end
- alias_method :remove_index, :remove_column
-
- def index(target_table_name, target_column_name, options={})
- column_name = options.delete(:name)
- column_name ||= [target_table_name, target_column_name].join("_")
- column_dir = Base.index_columns_directory(@definition.name,
- target_table_name.to_s)
- column_file = File.join(column_dir, "#{column_name}.groonga")
- options = {
- :with_position => true,
- :path => column_file,
- :name => column_name,
- }.merge(options)
- target_table = @definition.context[target_table_name]
- target_column = target_table.column(target_column_name)
- @definition.index(target_column, options)
- end
-
- def timestamps(*args)
- options = args.extract_options!
- column(:created_at, :datetime, options)
- column(:updated_at, :datetime, options)
- end
-
- def string(*args)
- columns("ShortText", *args)
- end
-
- def text(*args)
- columns("Text", *args)
- end
-
- def integer(*args)
- columns("Int32", *args)
- end
-
- def float(*args)
- columns("Float", *args)
- end
-
- def decimal(*args)
- columns("Int64", *args)
- end
-
- def time(*args)
- columns("Time", *args)
- end
- alias_method :datetime, :time
- alias_method :timestamp, :time
-
- def binary(*args)
- columns("LongText", *args)
- end
-
- def boolean(*args)
- columns("Bool", *args)
- end
-
- def reference(name, table=nil, options={})
- table = Base.groonga_table_name(table || name.to_s.pluralize)
- column(name, table, options)
- end
- alias_method :references, :reference
- alias_method :belongs_to, :references
-
- private
- def columns(type, *args)
- options = args.extract_options!
- column_names = args
- column_names.each do |name|
- column(name, type, options)
- end
- end
+ def update_version
+ management_table.update_version(@version)
end
end
end