migratrix 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/migratrix.rb CHANGED
@@ -5,12 +5,15 @@ module Migratrix
5
5
  APP=Pathname.new(__FILE__).dirname + "migratrix"
6
6
  EXT=Pathname.new(__FILE__).dirname + "patches"
7
7
 
8
- DEFAULT_MIGRATIONS_PATH = Rails.root + 'lib/migrations'
9
-
8
+ def self.default_migrations_path
9
+ Rails.root + 'lib/migrations'
10
+ end
10
11
 
11
12
  require EXT + 'string_ext'
12
13
  require EXT + 'object_ext'
13
14
  require EXT + 'andand'
15
+ require APP + 'logger'
16
+ require APP + 'loggable'
14
17
  require APP + 'exceptions'
15
18
  require APP + 'migration'
16
19
  require APP + 'migratrix'
@@ -0,0 +1,14 @@
1
+ module Migratrix
2
+ module Loggable
3
+ module ClassMethods
4
+ def logger
5
+ ::Migratrix::Logger.logger
6
+ end
7
+ end
8
+
9
+ def logger
10
+ ::Migratrix::Logger.logger
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,56 @@
1
+ module Migratrix
2
+ class Logger
3
+ attr_accessor :level, :stream
4
+
5
+ FATAL = 0
6
+ ERROR = 1
7
+ WARN = 2
8
+ DEBUG = 3
9
+ INFO = 4
10
+
11
+ @@singleton_instance = new
12
+
13
+ def self.logger
14
+ @@singleton_instance
15
+ end
16
+
17
+ def self.set_logger(stream=$stdout, level=INFO)
18
+ self.logger.stream=stream
19
+ self.logger.level=level
20
+ end
21
+
22
+ def initialize(stream, level)
23
+ # :nocov: SimpleCov can't see into this method.
24
+ @stream, @level = stream, level
25
+ end
26
+
27
+ def fatal(msg)
28
+ log(msg, FATAL)
29
+ end
30
+
31
+ def error(msg)
32
+ log(msg, ERROR)
33
+ end
34
+
35
+ def warn(msg)
36
+ log(msg, WARN)
37
+ end
38
+
39
+ def debug(msg)
40
+ log(msg, DEBUG)
41
+ end
42
+
43
+ def info(msg)
44
+ log(msg, INFO)
45
+ end
46
+
47
+ def log(msg, level)
48
+ if level <= @level
49
+ @stream.puts "%c %s: %s" % ["FEWDI"[level], Time.now.strftime("%F %T"), msg]
50
+ @stream.flush
51
+ end
52
+ end
53
+
54
+ private_class_method :new
55
+ end
56
+ end
@@ -2,21 +2,14 @@ module Migratrix
2
2
  # Superclass for all migrations. Migratrix COULD check to see that a
3
3
  # loaded migration inherits from this class, but hey, duck typing.
4
4
  class Migration
5
- attr_accessor :options, :logger
5
+ include ::Migratrix::Loggable
6
+ extend ::Migratrix::Loggable::ClassMethods
7
+
8
+ attr_accessor :options
6
9
 
7
10
  def initialize(options={})
8
11
  # cannot make a deep copy of an IO stream (e.g. logger) so make a shallow copy of it and move it out of the way
9
- @options = options.dup.tap {|h| @logger = h.delete("logger")}.deep_copy
10
-
11
- # if options["logger"]
12
- # @logger = options["logger"]
13
- # options = options.dup
14
- # options.delete["logger"]
15
- # end
16
- # @options = options.deep_copy
17
- # This should only be loaded if a) the Migration uses the AR
18
- # extract strategy and b) it's not already loaded
19
- # ::ActiveRecord::Base.send(:include, MigrationHelpers) unless ::ActiveRecord::Base.const_defined?("MigrationHelpers")
12
+ @options = options.deep_copy
20
13
  end
21
14
 
22
15
  # Load this data from source
@@ -41,12 +34,6 @@ module Migratrix
41
34
  transform
42
35
  load
43
36
  end
44
-
45
- def self.log(msg="", level=:info)
46
- return unless logger
47
- level = :info unless level.in? [:debug, :info, :warn, :error, :fatal, :unknown]
48
- logger.send level, "#{Time.now.strftime('%T')}: #{msg}"
49
- end
50
37
  end
51
38
  end
52
39
 
@@ -2,12 +2,25 @@
2
2
  # and integrating all the parts of a migration.
3
3
 
4
4
  module Migratrix
5
-
6
- def migrate(name, options={})
5
+ def self.migrate!(name, options={})
7
6
  ::Migratrix::Migratrix.migrate(name, options)
8
7
  end
9
8
 
9
+ def self.logger
10
+ ::Migratrix::Migratrix.logger
11
+ end
12
+
13
+ def self.logger=(new_logger)
14
+ ::Migratrix::Migratrix.logger= new_logger
15
+ end
16
+
10
17
  class Migratrix
18
+ include ::Migratrix::Loggable
19
+ extend ::Migratrix::Loggable::ClassMethods
20
+
21
+ def initialize
22
+ end
23
+
11
24
  def self.migrate(name, options={})
12
25
  migratrix = self.new()
13
26
  migration = migratrix.create_migration(name, options)
@@ -46,7 +59,7 @@ module Migratrix
46
59
  end
47
60
 
48
61
  def valid_options
49
- %w(limit where logger)
62
+ %w(limit where)
50
63
  end
51
64
 
52
65
  # ----------------------------------------------------------------------
@@ -69,30 +82,12 @@ module Migratrix
69
82
  # End MigrationRegistry
70
83
  # ----------------------------------------------------------------------
71
84
 
72
- # ----------------------------------------------------------------------
73
- # Migration path class accessors. Defaults to lib/migrations.
74
85
  def migrations_path
75
- @migrations_path ||= ::Migratrix::DEFAULT_MIGRATIONS_PATH
86
+ @migrations_path ||= ::Migratrix.default_migrations_path
76
87
  end
77
88
 
78
89
  def migrations_path=(new_path)
79
90
  @migrations_path = Pathname.new new_path
80
91
  end
81
-
82
- # def self.migrations_path
83
- # @@migrations_path ||= ::Migratrix::DEFAULT_MIGRATIONS_PATH
84
- # end
85
-
86
- # def self.migrations_path=(new_path)
87
- # @@migrations_path = Pathname.new new_path
88
- # end
89
- # End Migration path management
90
- # ----------------------------------------------------------------------
91
-
92
- # def self.log(msg="", level=:info)
93
- # return if quiet
94
- # level = :info unless level.in? [:debug, :info, :warn, :error, :fatal, :unknown]
95
- # logger.send level, "#{Time.now.strftime('%T')}: #{msg}"
96
- # end
97
92
  end
98
93
  end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe Migratrix::Logger do
4
+ let(:logger) { Migratrix::Logger.logger }
5
+
6
+ describe "sanity check kitty" do
7
+ it "is sanity checked" do
8
+ Migratrix::Logger.should_not be_nil
9
+ Migratrix::Logger.class.should == Class
10
+ end
11
+ end
12
+
13
+ describe "singleton-ness" do
14
+ it "is singleton-y" do
15
+ Migratrix::Logger.logger.class.should == Migratrix::Logger
16
+ end
17
+
18
+ it "cannot be new'ed" do
19
+ lambda { Migratrix::Logger.new }.should raise_error(NoMethodError)
20
+ end
21
+ end
22
+
23
+ describe "default" do
24
+ it "logs to $stdout" do
25
+ logger.stream == $stdout
26
+ end
27
+ end
28
+
29
+
30
+ describe "logging" do
31
+ let(:buffer) { StringIO.new }
32
+
33
+ before do
34
+ Timecop.freeze(Time.local(2011, 6, 28, 3, 14, 15))
35
+ end
36
+
37
+ after do
38
+ Timecop.return
39
+ end
40
+
41
+ it "formats info message with level and timestamp" do
42
+ with_logger_streaming_to(buffer) do
43
+ logger.info("Test Message")
44
+ buffer.string.should == "I 2011-06-28 03:14:15: Test Message\n"
45
+ end
46
+ end
47
+
48
+ it "formats debug message with level and timestamp" do
49
+ with_logger_streaming_to(buffer) do
50
+ logger.debug("Test Message")
51
+ buffer.string.should == "D 2011-06-28 03:14:15: Test Message\n"
52
+ end
53
+ end
54
+
55
+ it "formats warning message with level and timestamp" do
56
+ with_logger_streaming_to(buffer) do
57
+ logger.warn("Test Message")
58
+ buffer.string.should == "W 2011-06-28 03:14:15: Test Message\n"
59
+ end
60
+ end
61
+
62
+ it "formats error message with level and timestamp" do
63
+ with_logger_streaming_to(buffer) do
64
+ logger.error("Test Message")
65
+ buffer.string.should == "E 2011-06-28 03:14:15: Test Message\n"
66
+ end
67
+ end
68
+
69
+ it "formats fatal message with level and timestamp" do
70
+ with_logger_streaming_to(buffer) do
71
+ logger.fatal("Test Message")
72
+ buffer.string.should == "F 2011-06-28 03:14:15: Test Message\n"
73
+ end
74
+ end
75
+
76
+ it "rejects messages below logger level" do
77
+ with_logger_streaming_to(buffer, Migratrix::Logger::ERROR) do
78
+ logger.info("Test Message")
79
+ logger.debug("Test Message")
80
+ logger.warn("Test Message")
81
+ buffer.size.should == 0
82
+ logger.error("Test Error")
83
+ logger.fatal("Test Fatal")
84
+ buffer.string.should == "E 2011-06-28 03:14:15: Test Error\nF 2011-06-28 03:14:15: Test Fatal\n"
85
+ end
86
+ end
87
+ end
88
+
89
+ end
@@ -17,18 +17,6 @@ describe Migratrix::Migration do
17
17
  migration.options["where"].should == ["id=? AND approved=? AND pants=?", 42, true, false]
18
18
  conditions.should == ["id=? AND approved=?", 42, true]
19
19
  end
20
-
21
- it "safely moves logger option out of its options and into logger attribute" do
22
- conditions = ["id=? AND approved=?", 42, true]
23
- logger = Logger.new(StringIO.new)
24
- options = { "where" => conditions, "logger" => logger }
25
-
26
- migration = Migratrix::TestMigration.new(options)
27
-
28
- migration.options.should_not have_key("logger")
29
- migration.logger.should == logger
30
- options.should == { "where" => conditions, "logger" => logger }
31
- end
32
20
  end
33
21
 
34
22
  describe "#migrate" do
@@ -1,19 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- # Migatrix loads Migration classes into its namespace. In order to
4
- # test collision prevention, I needed to reach into Migratrix and
5
- # mindwipe it of any migrations. Here's the shiv to do that. I
6
- # originally put an API to do this on Migratrix but these specs are
7
- # the only clients of it so I removed it again. If you find a
8
- # legitimate use for it, feel free to re-add a remove_migration
9
- # method and send me a patch.
10
- def reset_migratrix!(migratrix)
11
- Migratrix.constants.map(&:to_s).select {|m| m =~ /.+Migration$/}.each do |migration|
12
- Migratrix.send(:remove_const, migration.to_sym)
13
- end
14
- migratrix.registered_migrations.clear
15
- end
16
-
17
3
  describe Migratrix::Migratrix do
18
4
  let (:migratrix) { Migratrix::Migratrix.new }
19
5
 
@@ -60,7 +46,7 @@ describe Migratrix::Migratrix do
60
46
 
61
47
  describe "#valid_options" do
62
48
  it "returns the valid set of option keys" do
63
- migratrix.valid_options.should == ["limit", "where", "logger"]
49
+ migratrix.valid_options.should == ["limit", "where"]
64
50
  end
65
51
  end
66
52
 
@@ -110,7 +96,31 @@ describe Migratrix::Migratrix do
110
96
  it "loads migration and migrates it" do
111
97
  Migratrix::Migratrix.stub!(:new).and_return(migratrix)
112
98
  Migratrix::Migratrix.migrate :marbles
113
- Migratrix::MarblesMigration.should be_migrated
99
+ end
100
+ end
101
+
102
+ describe ".logger" do
103
+ it "sets up a default logger to stdout" do
104
+ migratrix.logger.class.should == ::Migratrix::Logger
105
+ end
106
+ end
107
+
108
+ describe ".logger=" do
109
+ let (:migration) { migratrix.create_migration :marbles }
110
+ let (:buffer) { StringIO.new }
111
+
112
+ before do
113
+ reset_migratrix! migratrix
114
+ migratrix.migrations_path = SPEC + "fixtures/migrations"
115
+ end
116
+
117
+ it "sets logger globally across all Migratrices, the Migratrix module, Migrators and Models" do
118
+ with_logger_streaming_to(buffer) do
119
+ Migratrix.logger.stream.should == buffer
120
+ Migratrix::Migratrix.logger.stream.should == buffer
121
+ migratrix.logger.stream.should == buffer
122
+ migration.logger.stream.should == buffer
123
+ end
114
124
  end
115
125
  end
116
126
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Migratrix do
4
+ describe "sanity check kitty" do
5
+ it "is sanity checked" do
6
+ Migratrix.should_not be_nil
7
+ Migratrix.class.should == Module
8
+ end
9
+ end
10
+
11
+ describe ".migrate!" do
12
+ let (:migratrix) { Migratrix::Migratrix.new }
13
+
14
+ before do
15
+ reset_migratrix! migratrix
16
+ Migratrix::Migratrix.stub!(:new).and_return(migratrix)
17
+ migratrix.migrations_path = SPEC + "fixtures/migrations"
18
+ end
19
+
20
+ it "delegates to Migratrix::Migratrix" do
21
+ Migratrix.migrate! :marbles
22
+ Migratrix::MarblesMigration.should be_migrated
23
+ end
24
+ end
25
+
26
+ describe ".logger" do
27
+ it "delegates to Migratrix::Migratrix" do
28
+ Migratrix::Migratrix.should_receive(:logger).and_return nil
29
+ Migratrix.logger
30
+ end
31
+ end
32
+
33
+ describe ".logger=" do
34
+ let (:logger) { Logger.new(StringIO.new) }
35
+ it "delegates to Migratrix::Migratrix" do
36
+ Migratrix::Migratrix.should_receive(:logger=).with(logger).and_return nil
37
+ Migratrix.logger = logger
38
+ end
39
+ end
40
+ end
41
+
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ end
6
6
  require 'pathname'
7
7
  require 'ruby-debug'
8
8
  require 'rails'
9
+ require 'timecop'
9
10
  require 'logger'
10
11
 
11
12
  # Requires supporting ruby files with custom matchers and macros, etc,
@@ -26,6 +27,36 @@ Dir[SPEC + "support/**/*.rb"].each {|f| require f}
26
27
 
27
28
  require LIB + 'migratrix'
28
29
 
30
+ # Migatrix loads Migration classes into its namespace. In order to
31
+ # test collision prevention, I needed to reach into Migratrix and
32
+ # mindwipe it of any migrations. Here's the shiv to do that. I
33
+ # originally put an API to do this on Migratrix but these specs are
34
+ # the only clients of it so I removed it again. If you find a
35
+ # legitimate use for it, feel free to re-add a remove_migration
36
+ # method and send me a patch.
37
+ def reset_migratrix!(migratrix)
38
+ Migratrix.constants.map(&:to_s).select {|m| m =~ /.+Migration$/}.each do |migration|
39
+ Migratrix.send(:remove_const, migration.to_sym)
40
+ end
41
+ migratrix.registered_migrations.clear
42
+ end
43
+
44
+ # Redirect singleton logger to stream and level of our choice, then
45
+ # release it after the spec finishes or crashes.
46
+ def with_logger_streaming_to(stream, level=Migratrix::Logger::INFO, &block)
47
+ begin
48
+ old_stream, old_level = Migratrix::Logger.logger.stream, Migratrix::Logger.logger.level
49
+ Migratrix::Logger.set_logger(stream, level)
50
+ yield
51
+ ensure
52
+ Migratrix::Logger.set_logger old_stream, old_level
53
+ end
54
+ end
55
+
56
+
57
+
58
+
59
+
29
60
  RSpec.configure do |config|
30
61
  # == Mock Framework
31
62
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: migratrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-14 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: trollop
16
- requirement: &2153520180 !ruby/object:Gem::Requirement
16
+ requirement: &2161683820 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153520180
24
+ version_requirements: *2161683820
25
25
  description: Migratrix, a Rails legacy database migration tool supporting multiple
26
26
  strategies, including arbitrary n-ary migrations (1->n, n->1, n->m), arbitrary inputs
27
27
  and outputs (ActiveRecord, bare SQL, CSV) and migration logging
@@ -38,15 +38,19 @@ files:
38
38
  - lib/migratrix.rb
39
39
  - lib/migratrix/active_record_migration_helpers.rb
40
40
  - lib/migratrix/exceptions.rb
41
+ - lib/migratrix/loggable.rb
42
+ - lib/migratrix/logger.rb
41
43
  - lib/migratrix/migration.rb
42
44
  - lib/migratrix/migratrix.rb
43
45
  - lib/patches/andand.rb
44
46
  - lib/patches/object_ext.rb
45
47
  - lib/patches/string_ext.rb
46
48
  - spec/fixtures/migrations/marbles_migration.rb
49
+ - spec/lib/logger_spec.rb
47
50
  - spec/lib/migration_spec.rb
48
51
  - spec/lib/migrator_spec.rb
49
52
  - spec/lib/migratrix_spec.rb
53
+ - spec/migratrix_module_spec.rb
50
54
  - spec/patches/object_ext_spec.rb
51
55
  - spec/patches/string_ext_spec.rb
52
56
  - spec/spec_helper.rb