sqrbl 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,6 +1,29 @@
1
+ == 0.2.0 / 2009-09-03
2
+
3
+ * API change: switch to using the word "conversion" instead of
4
+ "migration" throughout the library. While this was mostly a
5
+ find-and-replace job, I'm bumping the version number to indicate the
6
+ API breakage.
7
+
8
+ I'd found that using the word "migration" got people thinking in terms
9
+ of ActiveRecord, which isn't quite the intended purpose of this
10
+ library. SQrbL was written to manage the process of doing one-off
11
+ database conversions in a repeatable way.
12
+
13
+ (At raSANTIAGO, I helped a few organizations switch from other
14
+ programs to CiviCRM, and I wrote SQrbL to help me keep track of all
15
+ the various steps involved in importing their legacy
16
+ constituent-management data to CiviCRM.)
17
+
18
+ == 0.1.3 / 2009-08-07
19
+
20
+ * Added Step#helpers method for code cosmetics.
21
+
1
22
  == 0.1.2 / 2009-08-06
2
23
 
3
- * No changes -- just want to make sure the latest release is actually usable after flailing around trying to use the 'bones' and 'rubyforge' gems.
24
+ * No changes -- just want to make sure the latest release is actually
25
+ usable after flailing around trying to use the 'bones' and 'rubyforge'
26
+ gems.
4
27
 
5
28
  == 0.1.0 / 2009-08-06
6
29
 
data/README.txt CHANGED
@@ -1,4 +1,4 @@
1
- == SQrbL: Making database migrations suck less since July 2009!
1
+ == SQrbL: Making database conversions suck less since July 2009!
2
2
 
3
3
  Copyright (c) 2009 raSANTIAGO + Associates LLC (http://www.rasantiago.com)
4
4
 
@@ -10,13 +10,13 @@ SQrbL's creator and primary author is Sam Livingston-Gray.
10
10
 
11
11
  == DESCRIPTION:
12
12
 
13
- SQrbL was created to help manage an extremely specific problem: managing SQL-based database migrations.
13
+ SQrbL was created to help manage an extremely specific problem: managing SQL-based database conversions.
14
14
 
15
15
  In essence, SQrbL is a tool for managing multiple SQL queries using Ruby. SQrbL borrows some terminology and ideas from ActiveRecord's schema migrations, but where ActiveRecord manages changes to your database schema over time, SQrbL was written to manage the process of transforming your data from one schema to another. (Of course, you could use SQrbL for the former case as well -- just use it to write DDL queries -- but ActiveRecord has better tools for figuring out which migrations have already been applied.)
16
16
 
17
17
  ===How It Works:
18
18
 
19
- You describe the steps in your migration in a SQrbL file. Each step can produce as much or as little SQL as you like. Each step has an "up" and a "down" part -- so you can do and undo each step as many times as you need to, until you get it just right. When you run your SQrbL file, it creates a tree of *.sql files containing the output from your migration steps, one file per step. It also creates the combined files "all_up.sql" and "all_down.sql"; these contain all of your steps combined into one giant file so that, when Cutover Day arrives, you can copy/paste the whole thing into your SQL client and run it all at once.
19
+ You describe the steps in your conversion in a SQrbL file. Each step can produce as much or as little SQL as you like. Each step has an "up" and a "down" part -- so you can do and undo each step as many times as you need to, until you get it just right. When you run your SQrbL file, it creates a tree of *.sql files containing the output from your conversion steps, one file per step. It also creates the combined files "all_up.sql" and "all_down.sql"; these contain all of your steps combined into one giant file so that, when Cutover Day arrives, you can copy/paste the whole thing into your SQL client and run it all at once.
20
20
 
21
21
  ===Why It Exists:
22
22
 
@@ -26,13 +26,21 @@ SQL is a fantastic DSL for describing queries. It's not bad at doing transforma
26
26
 
27
27
  SQL.rb seemed a bit too pretentious, so I went with SQrbL -- as in, "You got Ruby in my SQL." I pronounce it "squirble" (rhymes with "squirrel"). The proper capitalization can be annoying to type, so I've aliased the SQrbL class as Sqrbl.
28
28
 
29
+ Note: While not quite a literal pronunciation, "Screwball" is an accepted alternate. Mostly 'cause it's funny.
30
+
29
31
  == SYNOPSIS:
30
32
 
31
33
  <i>(Note that, in the following code sample, I'm using the convention that do/end blocks are used primarily for their side effects, and curly-brace blocks are used primarily for their return value.)</i>
32
34
 
33
- Sqrbl.migration "Convert from old widgets to new widgets" do
35
+ Sqrbl.conversion "Convert from old widgets to new widgets" do
34
36
  set_output_directory '/path/to/generated/sql'
35
37
 
38
+ helpers do
39
+ def widget_import_note
40
+ '"Imported from old_widgets"'
41
+ end
42
+ end
43
+
36
44
  group "Widgets" do
37
45
  step "Create widgets" do
38
46
  up do
@@ -42,7 +50,7 @@ SQL.rb seemed a bit too pretentious, so I went with SQrbL -- as in, "You got Rub
42
50
  insert_into("new_widgets", {
43
51
  :name => 'widget_name',
44
52
  :part_num => 'CONCAT("X_", part_number)',
45
- :note => '"Imported from old_widgets"',
53
+ :note => widget_import_note,
46
54
  })
47
55
  }
48
56
  FROM old_widgets
@@ -59,7 +67,7 @@ SQL.rb seemed a bit too pretentious, so I went with SQrbL -- as in, "You got Rub
59
67
  end
60
68
  end
61
69
 
62
- The above code sample describes a migration with one step: migrating the data in an `old_widgets` table to a `new_widgets` table. When run, this will generate a set of *.sql files in the directory /path/to/generated/sql.
70
+ The above code sample describes a conversion with one step: moving the data in an `old_widgets` table to a `new_widgets` table. When run, this will generate a set of *.sql files in the directory /path/to/generated/sql.
63
71
 
64
72
  == REQUIREMENTS:
65
73
 
data/TODO.txt CHANGED
@@ -1,11 +1,12 @@
1
+ - Change verbiage: "conversion" instead of "migration".
2
+
3
+ - Writers should create some sort of output to let you know that something happened.
4
+
1
5
  - bin/sqrbl should create an empty SQrbL file with the following simple template:
2
6
  require 'rubygems'
3
7
  require 'sqrbl'
4
- Sqrbl.migration do
8
+ Sqrbl.conversion do
5
9
  # (copy the rest from README.txt)
6
10
  end
7
11
 
8
- - Writers should create some sort of output to let you know that something happened.
9
-
10
- - Define #helper(&block) as a simple wrapper to instance_eval on the same object. (Purpose: allow you to define helpers in a block that can be code-folded.)
11
-
12
+ - Add some string-munging for pluralize(n, thing, things), and possibly move #unix_name into the string-munging module.
data/lib/sqrbl.rb CHANGED
@@ -2,11 +2,11 @@
2
2
  # For more information, please see README.txt and LICENSE.txt in the project's root directory.
3
3
  #
4
4
  # Most of this was autogenerated by the 'bones' gem.
5
- # The primary domain-specific method of interest here is Sqrbl.migration.
5
+ # The primary domain-specific method of interest here is Sqrbl.conversion.
6
6
  module Sqrbl
7
7
 
8
8
  # :stopdoc:
9
- VERSION = '0.1.2'
9
+ VERSION = '0.2.0'
10
10
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
11
11
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
12
12
  # :startdoc:
@@ -46,22 +46,22 @@ module Sqrbl
46
46
  Dir.glob(search_me).sort.each {|rb| require rb}
47
47
  end
48
48
 
49
- # Convenience method: builds and writes a migration in one go.
50
- def self.migration(&block)
51
- returning(build_migration(&block)) do |mig|
52
- write_migration!(mig)
49
+ # Convenience method: builds and writes a conversion in one go.
50
+ def self.conversion(&block)
51
+ returning(build_conversion(&block)) do |cvn|
52
+ write_conversion!(cvn)
53
53
  end
54
54
  end
55
55
 
56
- # Convenience method: Calls Sqrbl::Migration.build and passes it the given block.
57
- def self.build_migration(&block)
58
- Sqrbl::Migration.build(&block)
56
+ # Convenience method: Calls Sqrbl::Conversion.build and passes it the given block.
57
+ def self.build_conversion(&block)
58
+ Sqrbl::Conversion.build(&block)
59
59
  end
60
60
 
61
- # Convenience method: Write a Migration using all subclasses of BaseMigrationWriter.
62
- def self.write_migration!(migration)
63
- BaseMigrationWriter.subclasses.each do |writer_class|
64
- writer_class.write_migration!(migration)
61
+ # Convenience method: Write a Conversion using all subclasses of BaseConversionWriter.
62
+ def self.write_conversion!(conversion)
63
+ BaseConversionWriter.subclasses.each do |writer_class|
64
+ writer_class.write_conversion!(conversion)
65
65
  end
66
66
  end
67
67
 
@@ -1,9 +1,9 @@
1
1
  require 'fileutils'
2
2
 
3
3
  module Sqrbl
4
- # Base class for other migration writers.
5
- class BaseMigrationWriter
6
- attr_accessor :migration, :output_directory
4
+ # Base class for other conversion writers.
5
+ class BaseConversionWriter
6
+ attr_accessor :conversion, :output_directory
7
7
 
8
8
  class << self
9
9
  # List all classes that inherit from this one
@@ -16,23 +16,23 @@ module Sqrbl
16
16
  end
17
17
 
18
18
  # Convenience method: create a new instance and invoke <tt>write!</tt> on it.
19
- def write_migration!(migration)
20
- new(migration).write!
19
+ def write_conversion!(conversion)
20
+ new(conversion).write!
21
21
  end
22
22
  end
23
23
 
24
- def initialize(migration) #:nodoc:
25
- @migration = migration
24
+ def initialize(conversion) #:nodoc:
25
+ @conversion = conversion
26
26
  set_default_output_dir!
27
27
  end
28
28
 
29
29
  protected
30
30
  # Set the output_directory attribute based on the output_directory or creating_file
31
- # attributes of the given migration, in that order
31
+ # attributes of the given conversion, in that order
32
32
  def set_default_output_dir!
33
- raise "No migration given!" unless migration
34
- self.output_directory ||= migration.output_directory
35
- self.output_directory ||= migration.creating_file && File.join(File.expand_path(File.dirname(migration.creating_file)), 'sql')
33
+ raise "No conversion given!" unless conversion
34
+ self.output_directory ||= conversion.output_directory
35
+ self.output_directory ||= conversion.creating_file && File.join(File.expand_path(File.dirname(conversion.creating_file)), 'sql')
36
36
  raise "Unable to determine output directory!" unless self.output_directory
37
37
  end
38
38
 
@@ -4,27 +4,27 @@
4
4
 
5
5
  module Sqrbl
6
6
 
7
- # The Migration class doesn't do much on its own; it's basically just a
7
+ # The Conversion class doesn't do much on its own; it's basically just a
8
8
  # container for a list of Group objects, which are created using #group.
9
9
  #
10
10
  # Note also that because Group includes the MethodMissingDelegation mixin,
11
- # instance methods defined in the block given to Migration.build will become
11
+ # instance methods defined in the block given to Conversion.build will become
12
12
  # available to all groups (and their related objects) that belong to a
13
- # Migration instance. For more information, see MethodMissingDelegation.
14
- class Migration
13
+ # Conversion instance. For more information, see MethodMissingDelegation.
14
+ class Conversion
15
15
  attr_reader :groups, :creating_file, :output_directory
16
16
 
17
17
  include HasTodos
18
18
 
19
- # Creates a new Migration object and evaluates the block in its binding.
19
+ # Creates a new Conversion object and evaluates the block in its binding.
20
20
  # As a result, any methods called within the block will affect the state
21
21
  # of that object (and that object only).
22
22
  #
23
- # <i>(Eventually, this will also pass the migration to a helper object that
23
+ # <i>(Eventually, this will also pass the conversion to a helper object that
24
24
  # will create the tree of output *.sql files.)</i>
25
25
  def self.build(&block)
26
- returning(self.new) do |migration|
27
- migration.instance_eval(&block)
26
+ returning(self.new) do |conversion|
27
+ conversion.instance_eval(&block)
28
28
  end
29
29
  end
30
30
 
@@ -44,17 +44,17 @@ module Sqrbl
44
44
  groups << Group.new(self, name, &block)
45
45
  end
46
46
 
47
- # Convenience method: iterate all StepPair objects in the migration
47
+ # Convenience method: iterate all StepPair objects in the conversion
48
48
  def step_pairs
49
49
  groups.map(&:steps).flatten
50
50
  end
51
51
 
52
- # Convenience method: iterate all 'up' steps in the migration
52
+ # Convenience method: iterate all 'up' steps in the conversion
53
53
  def up_steps
54
54
  step_pairs.map(&:up_step)
55
55
  end
56
56
 
57
- # Convenience method: iterate all 'down' steps in the migration
57
+ # Convenience method: iterate all 'down' steps in the conversion
58
58
  def down_steps
59
59
  step_pairs.map(&:down_step)
60
60
  end
data/lib/sqrbl/group.rb CHANGED
@@ -3,21 +3,21 @@
3
3
 
4
4
 
5
5
  module Sqrbl
6
- # Like the Migration class, Group doesn't do much on its own.
6
+ # Like the Conversion class, Group doesn't do much on its own.
7
7
  # It's basically a container for a list of StepPair objects, which are created using #step.
8
8
  #
9
- # Group delegates +method_missing+ calls to its +migration+ object.
9
+ # Group delegates +method_missing+ calls to its +conversion+ object.
10
10
  # For more information, see MethodMissingDelegation.
11
11
  class Group
12
- attr_reader :migration, :description, :block, :steps
12
+ attr_reader :conversion, :description, :block, :steps
13
13
 
14
14
  include Sqrbl::ExpectsBlockWithNew
15
15
  include Sqrbl::MethodMissingDelegation
16
- delegate_method_missing_to :migration
16
+ delegate_method_missing_to :conversion
17
17
  include HasTodos
18
18
 
19
- def initialize(migration, description, options = {}, &block)
20
- @migration = migration
19
+ def initialize(conversion, description, options = {}, &block)
20
+ @conversion = conversion
21
21
  @description = description
22
22
  @block = lambda(&block)
23
23
  @steps = []
@@ -1,7 +1,7 @@
1
1
  module Sqrbl
2
- # Writes one [numbered] file per migration step, in two main directories: sql/up/ and sql/down/.
3
- # Migration steps are contained in a [numbered] subfolder that corresponds to the group.
4
- class IndividualMigrationWriter < BaseMigrationWriter
2
+ # Writes one [numbered] file per conversion step, in two main directories: sql/up/ and sql/down/.
3
+ # Conversion steps are contained in a [numbered] subfolder that corresponds to the group.
4
+ class IndividualConversionWriter < BaseConversionWriter
5
5
  # Prepare the up and down directories and populate them with individual files.
6
6
  #
7
7
  # WARNING: <b>RECURSIVELY DELETES ALL FILES</b> in output_directory/up and output_directory/down unless passed :safe_mode => true in the options hash!
@@ -22,7 +22,7 @@ module Sqrbl
22
22
 
23
23
  # Write out the contents of the individual files, each in its group's subfolder
24
24
  def write_individual_files!
25
- migration.groups.each_with_index do |group, idx|
25
+ conversion.groups.each_with_index do |group, idx|
26
26
  group_dir = "%0#{group_num_width}d_%s" % [idx + 1, group.unix_name]
27
27
  up_subdir = File.join(output_directory, 'up', group_dir)
28
28
  down_subdir = File.join(output_directory, 'down', group_dir)
@@ -38,7 +38,7 @@ module Sqrbl
38
38
  end
39
39
 
40
40
  def group_num_width # :nodoc:
41
- migration.groups.length.to_s.length
41
+ conversion.groups.length.to_s.length
42
42
  end
43
43
 
44
44
  def step_num_width(step) # :nodoc:
@@ -7,7 +7,7 @@ module Sqrbl
7
7
  # references to one another. The graph will have the following general shape
8
8
  # (where --> indicates a relationship that is generally one-to-many):
9
9
  #
10
- # Migration --> Group --> StepPair --> Step
10
+ # Conversion --> Group --> StepPair --> Step
11
11
  #
12
12
  # Also, because these various objects are created with blocks that are
13
13
  # instance_eval'd, those blocks can define helper methods that will be
@@ -16,14 +16,14 @@ module Sqrbl
16
16
  # Taken together, these two features (back-references and instance_eval)
17
17
  # let us provide a useful facility for defining helper methods inside a
18
18
  # block, and accessing them using scoping rules that work in an intuitive
19
- # manner. For example, if a Migration defines a method #foo, which is
19
+ # manner. For example, if a Conversion defines a method #foo, which is
20
20
  # later called from inside a Step's block, the Step can catch that call
21
21
  # using method_missing and delegate it to its StepPair, which in turn
22
- # will delegate to its Group, which in turn will delegate to its Migration.
22
+ # will delegate to its Group, which in turn will delegate to its Conversion.
23
23
  #
24
24
  # Confused yet? Here's a slightly modified version of the example in README.txt:
25
25
  #
26
- # Sqrbl.migration "Convert from old widgets to new widgets" do
26
+ # Sqrbl.conversion "Convert from old widgets to new widgets" do
27
27
  # def new_widget_insert()
28
28
  # insert_into("new_widgets", {
29
29
  # :name => 'widget_name',
data/lib/sqrbl/step.rb CHANGED
@@ -54,6 +54,13 @@ EOF
54
54
  eval_block_on_initialize(options)
55
55
  end
56
56
 
57
+ # This method is purely cosmetic. If you want to define a number
58
+ # of helpers and use your editor's code-folding features to
59
+ # collapse them all together, define them in a +helper+ block.
60
+ def helpers(&block)
61
+ yield
62
+ end
63
+
57
64
  # Writes a commented-out Todo item to +output+.
58
65
  #
59
66
  # Also, creates a Todo object that may be used to create console
@@ -2,7 +2,7 @@ module Sqrbl
2
2
  # Writes two files: output_directory/all_up.sql and output_directory/all_down.sql.
3
3
  # * output_directory/all_up.sql contains all 'up' steps, in creation order.
4
4
  # * output_directory/all_down.sql contains all 'down' steps, in reverse creation order.
5
- class UnifiedMigrationWriter < BaseMigrationWriter
5
+ class UnifiedConversionWriter < BaseConversionWriter
6
6
  # Create all_up.sql and all_down.sql in output_directory.
7
7
  def write!
8
8
  ensure_dir_exists(output_directory)
@@ -12,12 +12,12 @@ module Sqrbl
12
12
 
13
13
  # Output from all 'up' steps, in creation order
14
14
  def all_up_steps_output
15
- migration.up_steps.map(&:output).join
15
+ conversion.up_steps.map(&:output).join
16
16
  end
17
17
 
18
18
  # Output from all 'down' steps, in reverse creation order
19
19
  def all_down_steps_output
20
- migration.down_steps.reverse.map(&:output).join
20
+ conversion.down_steps.reverse.map(&:output).join
21
21
  end
22
22
 
23
23
  protected
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ include Sqrbl
4
+
5
+ describe BaseConversionWriter do
6
+ it "should know what its subclasses are" do
7
+ BaseConversionWriter.subclasses.should == [
8
+ IndividualConversionWriter,
9
+ UnifiedConversionWriter,
10
+ ]
11
+ end
12
+ end
@@ -2,9 +2,9 @@ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
2
 
3
3
  include Sqrbl
4
4
 
5
- describe IndividualMigrationWriter do
5
+ describe IndividualConversionWriter do
6
6
  before(:each) do
7
- @mig = Sqrbl.build_migration do
7
+ @cvn = Sqrbl.build_conversion do
8
8
  group 'Group one' do
9
9
  step 'Step one' do
10
10
  up { write 'Step one up' }
@@ -14,7 +14,7 @@ describe IndividualMigrationWriter do
14
14
  end
15
15
 
16
16
  @base_dir = File.expand_path(File.join(File.dirname(__FILE__), 'sql'))
17
- @writer = IndividualMigrationWriter.new(@mig)
17
+ @writer = IndividualConversionWriter.new(@cvn)
18
18
  end
19
19
 
20
20
  it "should have a output_directory attribute" do
@@ -36,9 +36,9 @@ describe IndividualMigrationWriter do
36
36
  end
37
37
  end
38
38
 
39
- describe "for a migration with two groups and three steps" do
39
+ describe "for a conversion with two groups and three steps" do
40
40
  before(:each) do
41
- @mig = Sqrbl.build_migration do
41
+ @cvn = Sqrbl.build_conversion do
42
42
  group 'Group one' do
43
43
  step 'Step one' do
44
44
  up { write 'Step one up' }
@@ -58,11 +58,11 @@ describe IndividualMigrationWriter do
58
58
  end
59
59
 
60
60
  @base_dir = File.expand_path(File.join(File.dirname(__FILE__), 'sql'))
61
- @writer = IndividualMigrationWriter.new(@mig)
61
+ @writer = IndividualConversionWriter.new(@cvn)
62
62
  end
63
63
 
64
64
  it "should create a separate subdirectory in [output_directory]/up for each group" do
65
- @mig.groups.each_with_index do |group, idx|
65
+ @cvn.groups.each_with_index do |group, idx|
66
66
  group_dir = "#{idx + 1}_#{group.unix_name}"
67
67
  up_subdir = File.join(@writer.output_directory, 'up', group_dir)
68
68
  down_subdir = File.join(@writer.output_directory, 'down', group_dir)
@@ -76,7 +76,7 @@ describe IndividualMigrationWriter do
76
76
  end
77
77
 
78
78
  it "should create a separate file for each step, in the subdirectory for that step's group" do
79
- @mig.groups.each_with_index do |group, idx|
79
+ @cvn.groups.each_with_index do |group, idx|
80
80
  group_dir = "#{idx + 1}_#{group.unix_name}"
81
81
  up_subdir = File.join(@writer.output_directory, 'up', group_dir)
82
82
  down_subdir = File.join(@writer.output_directory, 'down', group_dir)
@@ -93,9 +93,9 @@ describe IndividualMigrationWriter do
93
93
  end
94
94
  end
95
95
 
96
- describe "for a migration with 10 groups" do
96
+ describe "for a conversion with 10 groups" do
97
97
  before(:each) do
98
- @mig = Sqrbl.build_migration do
98
+ @cvn = Sqrbl.build_conversion do
99
99
  group 'Group one' do
100
100
  step 'Step one' do
101
101
  up { write 'Step one up' }
@@ -158,7 +158,7 @@ describe IndividualMigrationWriter do
158
158
  end
159
159
  end
160
160
 
161
- @writer = IndividualMigrationWriter.new(@mig)
161
+ @writer = IndividualConversionWriter.new(@cvn)
162
162
  end
163
163
 
164
164
  it "should left-fill the group numbers with zeros" do
@@ -2,26 +2,26 @@ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
2
 
3
3
  include Sqrbl
4
4
 
5
- describe UnifiedMigrationWriter do
6
- describe "for a migration with #output_directory set" do
7
- it "should set #output_directory from the migration's #output_directory" do
8
- mig = mock('Migration', :output_directory => '/path/to/sql', :creating_file => nil)
9
- writer = UnifiedMigrationWriter.new(mig)
10
- writer.output_directory.should == mig.output_directory
5
+ describe UnifiedConversionWriter do
6
+ describe "for a conversion with #output_directory set" do
7
+ it "should set #output_directory from the conversion's #output_directory" do
8
+ cvn = mock('Conversion', :output_directory => '/path/to/sql', :creating_file => nil)
9
+ writer = UnifiedConversionWriter.new(cvn)
10
+ writer.output_directory.should == cvn.output_directory
11
11
  end
12
12
  end
13
13
 
14
- describe "for a migration with output_directory blank" do
15
- it "should set #output_directory using the dirname of the migration's #creating_file, plus /sql" do
16
- mig = mock('Migration', :output_directory => nil, :creating_file => '/path/to/some/sqrbl_file.rb')
17
- writer = UnifiedMigrationWriter.new(mig)
14
+ describe "for a conversion with output_directory blank" do
15
+ it "should set #output_directory using the dirname of the conversion's #creating_file, plus /sql" do
16
+ cvn = mock('Conversion', :output_directory => nil, :creating_file => '/path/to/some/sqrbl_file.rb')
17
+ writer = UnifiedConversionWriter.new(cvn)
18
18
  writer.output_directory.should == '/path/to/some/sql'
19
19
  end
20
20
  end
21
21
 
22
- describe "for a migration with two groups and three steps" do
22
+ describe "for a conversion with two groups and three steps" do
23
23
  before(:each) do
24
- @mig = Sqrbl.build_migration do
24
+ @cvn = Sqrbl.build_conversion do
25
25
  group 'Group one' do
26
26
  step 'Step one' do
27
27
  up { write 'Step one up' }
@@ -41,7 +41,7 @@ describe UnifiedMigrationWriter do
41
41
  end
42
42
 
43
43
  @base_dir = File.expand_path(File.join(File.dirname(__FILE__), 'sql'))
44
- @writer = UnifiedMigrationWriter.new(@mig)
44
+ @writer = UnifiedConversionWriter.new(@cvn)
45
45
  end
46
46
 
47
47
  it "should not create the target directory if it already exists" do
@@ -65,7 +65,7 @@ describe UnifiedMigrationWriter do
65
65
  end
66
66
 
67
67
  it "should combine the contents of all up steps in order" do
68
- @writer.all_up_steps_output.should == @mig.up_steps.map(&:output).join
68
+ @writer.all_up_steps_output.should == @cvn.up_steps.map(&:output).join
69
69
  end
70
70
 
71
71
  it "should write the contents of all up steps to the all_up.sql file" do
@@ -83,7 +83,7 @@ describe UnifiedMigrationWriter do
83
83
  end
84
84
 
85
85
  it "should combine the contents of all down steps in REVERSE order" do
86
- @writer.all_down_steps_output.should == @mig.down_steps.reverse.map(&:output).join
86
+ @writer.all_down_steps_output.should == @cvn.down_steps.reverse.map(&:output).join
87
87
  end
88
88
 
89
89
  it "should write the contents of all down steps to the all_down.sql file" do
data/spec/spec_helper.rb CHANGED
@@ -19,7 +19,7 @@ Spec::Runner.configure do |config|
19
19
  end
20
20
 
21
21
 
22
- # Stub out the various things that the migration writers do.
22
+ # Stub out the various things that the conversion writers do.
23
23
  # Call this after defining the mocks you care about (because mocks created first take precedence).
24
24
  # Then, calling #write! shouldn't actually touch the filesystem.
25
25
  def stub_out_file_creation
@@ -2,35 +2,35 @@ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
2
 
3
3
  include Sqrbl
4
4
 
5
- describe Migration do
6
- describe "A new migration" do
5
+ describe Conversion do
6
+ describe "A new conversion" do
7
7
  it "should know the file that created it" do
8
- mig = Migration.new
9
- mig.creating_file.should == File.expand_path(__FILE__)
8
+ cvn = Conversion.new
9
+ cvn.creating_file.should == File.expand_path(__FILE__)
10
10
  end
11
11
  end
12
12
 
13
- describe "A migration built with Migration.build" do
13
+ describe "A conversion built with Conversion.build" do
14
14
  it "should still know the file that created it" do
15
- mig = Migration.build {}
16
- mig.creating_file.should == File.expand_path(__FILE__)
15
+ cvn = Conversion.build {}
16
+ cvn.creating_file.should == File.expand_path(__FILE__)
17
17
  end
18
18
 
19
19
  describe "when the block calls #group once" do
20
20
  it "should have one group with the proper description" do
21
- mig = Migration.build do
21
+ cvn = Conversion.build do
22
22
  group "first group" do
23
23
  'hello world'
24
24
  end
25
25
  end
26
- mig.groups.all? { |group| group.should be_kind_of(Group) }
27
- mig.groups.map(&:description).should == ['first group']
26
+ cvn.groups.all? { |group| group.should be_kind_of(Group) }
27
+ cvn.groups.map(&:description).should == ['first group']
28
28
  end
29
29
  end
30
30
 
31
31
  describe "when the block calls #group twice" do
32
32
  it "should have two group with the proper descriptions" do
33
- mig = Migration.build do
33
+ cvn = Conversion.build do
34
34
  group "first group" do
35
35
  'hello world'
36
36
  end
@@ -38,31 +38,31 @@ describe Migration do
38
38
  'goodbye world'
39
39
  end
40
40
  end
41
- mig.groups.all? { |group| group.should be_kind_of(Group) }
42
- mig.groups.map(&:description).should == ['first group', 'second group']
41
+ cvn.groups.all? { |group| group.should be_kind_of(Group) }
42
+ cvn.groups.map(&:description).should == ['first group', 'second group']
43
43
  end
44
44
  end
45
45
 
46
46
  it "should pass itself as a dependency to any group it builds" do
47
- mig = Migration.build do
47
+ cvn = Conversion.build do
48
48
  group("first group" ) { '' }
49
49
  group("second group" ) { '' }
50
50
  group("group the third") { '' }
51
51
  end
52
52
 
53
- mig.groups.all? { |group| group.migration.should == mig }
53
+ cvn.groups.all? { |group| group.conversion.should == cvn }
54
54
  end
55
55
  end
56
56
 
57
57
  describe "when #todo is called" do
58
58
  it "should create a Todo object that saves the message" do
59
- mig = Migration.build { todo 'foo' }
60
- mig.todos.map(&:message).should == ['foo']
59
+ cvn = Conversion.build { todo 'foo' }
60
+ cvn.todos.map(&:message).should == ['foo']
61
61
  end
62
62
 
63
63
  it "should create a Todo object that saves the location of the #todo call" do
64
- mig = Migration.build { todo 'foo' }; line_num = __LINE__
65
- mig.todos.first.location.should == [__FILE__, line_num].join(':')
64
+ cvn = Conversion.build { todo 'foo' }; line_num = __LINE__
65
+ cvn.todos.first.location.should == [__FILE__, line_num].join(':')
66
66
  end
67
67
  end
68
68
  end
@@ -4,26 +4,26 @@ include Sqrbl
4
4
 
5
5
  describe Group do
6
6
  before(:each) do
7
- @mig = mock('Migration')
7
+ @cvn = mock('Conversion')
8
8
  end
9
9
 
10
10
  it "should evaluate the block in its own context" do
11
- group = Group.new(@mig, "foo", :skip_block_evaluation => true) do
11
+ group = Group.new(@cvn, "foo", :skip_block_evaluation => true) do
12
12
  hello_world()
13
13
  end
14
14
  group.should_receive(:hello_world)
15
15
  group.send(:evaluate_block!)
16
16
  end
17
17
 
18
- it "should delegate method_missing calls back to the migration object" do
19
- @mig.should_receive(:goodbye_world)
20
- group = Group.new(@mig, "foo") do
18
+ it "should delegate method_missing calls back to the conversion object" do
19
+ @cvn.should_receive(:goodbye_world)
20
+ group = Group.new(@cvn, "foo") do
21
21
  goodbye_world()
22
22
  end
23
23
  end
24
24
 
25
25
  it "methods defined in the group block should become available as methods on the Group instance" do
26
- group = Group.new(@mig, "foo") do
26
+ group = Group.new(@cvn, "foo") do
27
27
  def hello_world
28
28
  "Hello, world!"
29
29
  end
@@ -34,12 +34,12 @@ describe Group do
34
34
 
35
35
  describe "when #todo is called" do
36
36
  it "should create a Todo object that saves the message" do
37
- group = Group.new(@mig, 'foo') { todo 'bar' }
37
+ group = Group.new(@cvn, 'foo') { todo 'bar' }
38
38
  group.todos.map(&:message).should == ['bar']
39
39
  end
40
40
 
41
41
  it "should create a Todo object that saves the location of the #todo call" do
42
- group = Group.new(@mig, 'foo') { todo 'bar' }; line_num = __LINE__
42
+ group = Group.new(@cvn, 'foo') { todo 'bar' }; line_num = __LINE__
43
43
  group.todos.first.location.should == [__FILE__, line_num].join(':')
44
44
  end
45
45
  end
@@ -47,7 +47,7 @@ describe Group do
47
47
  describe "when #step is called" do
48
48
  it "should create a StepPair object and pass it the group, the description, and the block arg" do
49
49
  test_self = self
50
- group = Group.new(@mig, "foo") do
50
+ group = Group.new(@cvn, "foo") do
51
51
  StepPair.should_receive(:new).with(self, 'do something').and_yield # Look weird? See ./README.txt
52
52
  step('do something') {}
53
53
  end
@@ -56,18 +56,18 @@ describe Group do
56
56
 
57
57
  describe :valid? do
58
58
  it "should return false if steps is empty" do
59
- group = Group.new(@mig, "foo") {}
59
+ group = Group.new(@cvn, "foo") {}
60
60
  group.should_not be_valid
61
61
  end
62
62
 
63
63
  it "should return false if steps is not empty, but any step is invalid" do
64
- group = Group.new(@mig, "foo") { step("foo") {} }
64
+ group = Group.new(@cvn, "foo") { step("foo") {} }
65
65
  group.steps.map(&:valid?).should include(false)
66
66
  group.should_not be_valid
67
67
  end
68
68
 
69
69
  it "should return true if steps is not empty, and all steps are themselves valid" do
70
- group = Group.new(@mig, "foo") do
70
+ group = Group.new(@cvn, "foo") do
71
71
  step("foo") do
72
72
  up {}
73
73
  down {}
@@ -78,7 +78,7 @@ describe Group do
78
78
  end
79
79
 
80
80
  it "should have a unix_name property that consists of the regular name with characters sanitized" do
81
- group = Group.new(@mig, "This be a test, matey! ARRR!!") {}
81
+ group = Group.new(@cvn, "This be a test, matey! ARRR!!") {}
82
82
  group.unix_name.should == 'this_be_a_test_matey_arrr'
83
83
  end
84
84
 
@@ -3,25 +3,25 @@ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
3
3
  include Sqrbl
4
4
 
5
5
  describe Sqrbl do
6
- it ".build_migration should return an instance of Sqrbl::Migration" do
7
- migration = Sqrbl.build_migration { 'hello, world!' }
8
- migration.should be_kind_of(Sqrbl::Migration)
6
+ it ".build_conversion should return an instance of Sqrbl::Conversion" do
7
+ conversion = Sqrbl.build_conversion { 'hello, world!' }
8
+ conversion.should be_kind_of(Sqrbl::Conversion)
9
9
  end
10
10
 
11
- it ".migration should take the return value from Sqrbl::Migration.build and pass it to write_migration" do
12
- mig = mock('Migration')
13
- Migration.should_receive(:build).and_yield.and_return(mig)
14
- Sqrbl.should_receive(:write_migration!).with(mig)
15
- Sqrbl.migration { 'Hello, world!' }
11
+ it ".conversion should take the return value from Sqrbl::Conversion.build and pass it to write_conversion" do
12
+ cvn = mock('Conversion')
13
+ Conversion.should_receive(:build).and_yield.and_return(cvn)
14
+ Sqrbl.should_receive(:write_conversion!).with(cvn)
15
+ Sqrbl.conversion { 'Hello, world!' }
16
16
  end
17
17
 
18
- describe :write_migration! do
19
- it "should take a migration object and pass it off to any and all writers that exist" do
20
- mig = mock('Migration')
21
- BaseMigrationWriter.subclasses.each do |writer_class|
22
- writer_class.should_receive(:write_migration!).with(mig)
18
+ describe :write_conversion! do
19
+ it "should take a conversion object and pass it off to any and all writers that exist" do
20
+ cvn = mock('Conversion')
21
+ BaseConversionWriter.subclasses.each do |writer_class|
22
+ writer_class.should_receive(:write_conversion!).with(cvn)
23
23
  end
24
- Sqrbl.write_migration!(mig)
24
+ Sqrbl.write_conversion!(cvn)
25
25
  end
26
26
  end
27
27
 
@@ -32,6 +32,18 @@ describe Step do
32
32
  step.hello_world.should == "Hello, world!"
33
33
  end
34
34
 
35
+ it "methods defined in a #helpers block should become available as methods on the Step instance" do
36
+ step = Step.new(@pair) do
37
+ helpers do
38
+ def hello_world
39
+ "Hello, world!"
40
+ end
41
+ end
42
+ end
43
+ step.should respond_to(:hello_world)
44
+ step.hello_world.should == "Hello, world!"
45
+ end
46
+
35
47
  describe "when #todo is called" do
36
48
  it "should create a Todo object that saves the message" do
37
49
  step = Step.new(@pair) { todo 'foo' }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqrbl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Livingston-Gray
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-06 00:00:00 -07:00
12
+ date: 2009-09-04 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -23,7 +23,7 @@ dependencies:
23
23
  version: 2.5.1
24
24
  version:
25
25
  description: |-
26
- SQrbL was created to help manage an extremely specific problem: managing SQL-based database migrations.
26
+ SQrbL was created to help manage an extremely specific problem: managing SQL-based database conversions.
27
27
 
28
28
  In essence, SQrbL is a tool for managing multiple SQL queries using Ruby. SQrbL borrows some terminology and ideas from ActiveRecord's schema migrations, but where ActiveRecord manages changes to your database schema over time, SQrbL was written to manage the process of transforming your data from one schema to another. (Of course, you could use SQrbL for the former case as well -- just use it to write DDL queries -- but ActiveRecord has better tools for figuring out which migrations have already been applied.)
29
29
  email: geeksam@gmail.com
@@ -48,24 +48,24 @@ files:
48
48
  - lib/core_exts/object.rb
49
49
  - lib/core_exts/symbol.rb
50
50
  - lib/sqrbl.rb
51
- - lib/sqrbl/base_migration_writer.rb
51
+ - lib/sqrbl/base_conversion_writer.rb
52
52
  - lib/sqrbl/call_stack.rb
53
+ - lib/sqrbl/conversion.rb
53
54
  - lib/sqrbl/group.rb
54
- - lib/sqrbl/individual_migration_writer.rb
55
- - lib/sqrbl/migration.rb
55
+ - lib/sqrbl/individual_conversion_writer.rb
56
56
  - lib/sqrbl/mixins/expects_block_with_new.rb
57
57
  - lib/sqrbl/mixins/has_todos.rb
58
58
  - lib/sqrbl/mixins/method_missing_delegation.rb
59
59
  - lib/sqrbl/step.rb
60
60
  - lib/sqrbl/step_pair.rb
61
- - lib/sqrbl/unified_migration_writer.rb
61
+ - lib/sqrbl/unified_conversion_writer.rb
62
62
  - spec/README.txt
63
- - spec/functional/base_migration_writer_spec.rb
64
- - spec/functional/individual_migration_writer_spec.rb
65
- - spec/functional/unified_migration_writer_spec.rb
63
+ - spec/functional/base_conversion_writer_spec.rb
64
+ - spec/functional/individual_conversion_writer_spec.rb
65
+ - spec/functional/unified_conversion_writer_spec.rb
66
66
  - spec/spec_helper.rb
67
+ - spec/unit/conversion_spec.rb
67
68
  - spec/unit/group_spec.rb
68
- - spec/unit/migration_spec.rb
69
69
  - spec/unit/sqrbl_spec.rb
70
70
  - spec/unit/step_pair_spec.rb
71
71
  - spec/unit/step_spec.rb
@@ -110,6 +110,6 @@ rubyforge_project: sqrbl
110
110
  rubygems_version: 1.3.4
111
111
  signing_key:
112
112
  specification_version: 3
113
- summary: "SQrbL was created to help manage an extremely specific problem: managing SQL-based database migrations"
113
+ summary: "SQrbL was created to help manage an extremely specific problem: managing SQL-based database conversions"
114
114
  test_files: []
115
115
 
@@ -1,12 +0,0 @@
1
- require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
-
3
- include Sqrbl
4
-
5
- describe BaseMigrationWriter do
6
- it "should know what its subclasses are" do
7
- BaseMigrationWriter.subclasses.should == [
8
- IndividualMigrationWriter,
9
- UnifiedMigrationWriter,
10
- ]
11
- end
12
- end