※2016-10-20時点の情報です(ridgepole/master 021728f9ff31d35eb5b7f3ee113a7938f429e864
)
ridgepoleは内部でActiveRecordを使っている。
現状のスキーマとSchemafileの差分を取る部分のコード(delta.rb 464行、diff.rb 405行)がやや長いが、それ以外はけっこうシンプルなようだ。
現状のスキーマの取得方法
ActiveRecord::SchemaDumper.dump
を使っている。このメソッドによりRailsのdb/schema.rb
の内容と同じ文字列が得られる。
lib/ridgepole/dumper.rb
class Ridgepole::Dumper
def initialize(options = {})
@options = options
end
def dump
stream = StringIO.new
conn = ActiveRecord::Base.connection
(中略)
ActiveRecord::SchemaDumper.dump(conn, stream)
DSL(Schemafile)で使えるキーワード
lib/ridgepole/dsl_parser.rb
に書いてある。
lib/ridgepole/dsl_parser.rb
TYPES = [
# https://github.com/rails/rails/blob/v4.2.1/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L274 :string,
:text,
:integer,
:bigint,
:float,
:decimal,
:datetime,
:timestamp,
:time,
:date,
:binary,
:boolean,
(略)
DSLのパースにはinstance_eval
している。
create_table
、add_index
などのメソッドは独自に定義している。
dsl_parser.rb
def self.eval(dsl, opts = {})
ctx = self.new(opts)
if opts[:path]
ctx.instance_eval(dsl, opts[:path])
else
ctx.instance_eval(dsl)
end
[ctx.__definition, ctx.__execute]
end
def create_table(table_name, options = {})
table_name = table_name.to_s
table_definition = TableDefinition.new(table_name, self)
[:primary_key].each do |key|
options[key] = options[key].to_s if options[key]
end
yield(table_definition)
@__definition[table_name] ||= {}
if @__definition[table_name][:definition]
raise "Table `#{table_name}` already defined"
end
@__definition[table_name][:definition] = table_definition.__definition
options.delete(:force)
@__definition[table_name][:options] = options
end