Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Sven Fuchs committed Aug 11, 2011
0 parents commit 6842d01
Show file tree
Hide file tree
Showing 11 changed files with 451 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Gemfile
@@ -0,0 +1,18 @@
source :rubygems

gemspec

group :development, :test do
platforms :mri_18 do
# required as linecache uses it but does not have it as a dep
gem "require_relative", "~> 1.0.1"
gem 'ruby-debug'
end

unless RUBY_VERSION == '1.9.3' && RUBY_PLATFORM !~ /darwin/
# will need to install ruby-debug19 manually for 1.9.3:
# gem install ruby-debug19 -- --with-ruby-include=$rvm_path/src/ruby-1.9.3-preview1
gem 'ruby-debug19', :platforms => :mri_19
end
end

59 changes: 59 additions & 0 deletions Gemfile.lock
@@ -0,0 +1,59 @@
PATH
remote: .
specs:
data_migrations (0.0.1)
activerecord

GEM
remote: http://rubygems.org/
specs:
activemodel (3.0.9)
activesupport (= 3.0.9)
builder (~> 2.1.2)
i18n (~> 0.5.0)
activerecord (3.0.9)
activemodel (= 3.0.9)
activesupport (= 3.0.9)
arel (~> 2.0.10)
tzinfo (~> 0.3.23)
activesupport (3.0.9)
archive-tar-minitar (0.5.2)
arel (2.0.10)
builder (2.1.2)
columnize (0.3.4)
i18n (0.5.0)
linecache (0.46)
rbx-require-relative (> 0.0.4)
linecache19 (0.5.12)
ruby_core_source (>= 0.1.4)
pg (0.11.0)
rbx-require-relative (0.0.5)
require_relative (1.0.2)
ruby-debug (0.10.4)
columnize (>= 0.1)
ruby-debug-base (~> 0.10.4.0)
ruby-debug-base (0.10.4)
linecache (>= 0.3)
ruby-debug-base19 (0.11.25)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby_core_source (>= 0.1.4)
ruby-debug19 (0.11.6)
columnize (>= 0.3.1)
linecache19 (>= 0.5.11)
ruby-debug-base19 (>= 0.11.19)
ruby_core_source (0.1.5)
archive-tar-minitar (>= 0.5.2)
test_declarative (0.0.5)
tzinfo (0.3.29)

PLATFORMS
ruby

DEPENDENCIES
data_migrations!
pg
require_relative (~> 1.0.1)
ruby-debug
ruby-debug19
test_declarative
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
MIT LICENSE

Copyright (c) Sven Fuchs <svenfuchs@artweb-design.de>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
21 changes: 21 additions & 0 deletions README.md
@@ -0,0 +1,21 @@
# data\_migrations

class CreateRepositories < ActiveRecord::Migration
def self.up
create_table :tests do |t|
# ...
end

migrate_table :builds, :to => :tests |t|
t.where 'parent_id IS NULL'
t.move :number
t.copy :result, :to => :status
t.copy :commit, :result, :to => [:hash, :status]
t.copy :all, :except => :foo
t.exec 'UPDATE foo ...'
end
end

def self.down
end
end
10 changes: 10 additions & 0 deletions Rakefile
@@ -0,0 +1,10 @@
require 'rake'
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs << 'lib'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end

task :default => :test
23 changes: 23 additions & 0 deletions data_migrations.gemspec
@@ -0,0 +1,23 @@
# encoding: utf-8

$:.unshift File.expand_path('../lib', __FILE__)
require 'data_migrations/version'

Gem::Specification.new do |s|
s.name = "data_migrations"
s.version = DataMigrations::VERSION
s.authors = ["Sven Fuchs"]
s.email = "svenfuchs@artweb-design.de"
s.homepage = "https://github.com/svenfuchs/data_migrations"
s.summary = "[summary]"
s.description = "[description]"

s.files = Dir['{lib/**/*,[A-Z]*}']
s.platform = Gem::Platform::RUBY
s.require_path = 'lib'
s.rubyforge_project = '[none]'

s.add_dependency 'activerecord'
s.add_development_dependency 'test_declarative'
s.add_development_dependency 'pg'
end
173 changes: 173 additions & 0 deletions lib/data_migrations.rb
@@ -0,0 +1,173 @@
require 'active_record'
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/array/extract_options'

module DataMigrations
class Definition
attr_reader :source, :target, :instructions

def initialize(source, options = {})
@source = Table.new(source)
@target = Table.new(options[:to])
@instructions = []

yield self
end

def condition(condition = nil)
condition ? @condition = condition : @condition
end
alias :where :condition

def move(*columns)
options = columns.extract_options!
instructions << Move.new(self, columns, options)
end

def copy(*columns)
options = columns.extract_options!
instructions << Copy.new(self, columns, options)
end

def exec(sql)
instructions << Exec.new(self, sql)
end
end

class Table
delegate :connection, :to => :'ActiveRecord::Base'

attr_reader :name

def initialize(name)
@name = name
end

def columns
@columns ||= connection.columns(name)
end

def column(name)
columns.detect { |column| column.name.to_s == name.to_s } || raise_column_not_found(name)
end

def quoted_name
connection.quote_table_name(name)
end

def raise_column_not_found(name)
raise "could not find column #{name} on #{self.name}"
end
end

class Column
attr_reader :table, :name, :alias

def initialize(table, name, alias_)
@table = table
@name = name
@alias = alias_
end

def aliased
self.alias ? "#{quote(name)} AS #{quote(self.alias)}" : quote(name)
end

def definition
[quote(self.alias || name), type].join(' ')
end

def type
column.sql_type
end

def column
@column ||= table.column(name)
end

def quoted_name
quote(name)
end

def quote(name)
ActiveRecord::Base.connection.quote_column_name(name)
end
end

class Instruction
delegate :connection, :to => :'ActiveRecord::Base'
delegate :condition, :to => :definition

attr_reader :definition

def initialize(definition)
@definition = definition
end

def execute
statements.each { |statement| connection.execute(statement) }
end

def source
definition.source
end

def target
definition.target
end

def columns=(columns)
@columns = columns.map { |column, alias_| Column.new(definition.source, column, alias_) }
end

def aliased_column_names
columns.map(&:aliased).join(', ')
end

def column_definitions
columns.map(&:definition).join(', ')
end
end

class Copy < Instruction
attr_reader :columns, :options

def initialize(definition, columns, options)
super(definition)
self.columns = columns.zip(Array(options[:to]))
end

def statements
[insert_statement]
end

def insert_statement
statement = "INSERT INTO #{target.quoted_name} SELECT #{aliased_column_names} FROM #{source.quoted_name} "
statement << "WHERE #{condition} " if condition
statement << "AS t(#{column_definitions})"
end
end

class Move < Copy
def statements
super + drop_statements
end

def drop_statements
columns.map do |column|
"ALTER TABLE #{source.quoted_name} DROP COLUMN #{column.quoted_name}"
end
end
end

def Runner
attr_reader :definition

def initialize(definition)
@definition = definition
end

def run!
end
end
end
3 changes: 3 additions & 0 deletions lib/data_migrations/version.rb
@@ -0,0 +1,3 @@
module DataMigrations
VERSION = "0.0.1"
end

0 comments on commit 6842d01

Please sign in to comment.