dbmanager 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ ## v0.1.0
2
+
3
+ * major code refactoring
4
+ * allow mixed adapters in database.yml
5
+ * import process dumps to rails app tmp directory
6
+
1
7
  ## v0.0.6
2
8
 
3
9
  * handle mysql2 adapter
data/README.md CHANGED
@@ -32,9 +32,9 @@ rake db:dump
32
32
  ```
33
33
  This rake task will dump the requested db to a file on the local machine.
34
34
 
35
- You will be prompted to choose the target dir (defaults to tmp) and the sql file
36
- name (sql extension will be added automatically). If the file already exists, it
37
- will be overwritten.
35
+ **You will be prompted to choose the target dir** (defaults to *tmp* in the rails
36
+ root) and the sql file name (sql extension will be added automatically). If the
37
+ file already exists, it will be overwritten.
38
38
 
39
39
 
40
40
  #### Database Imports
@@ -43,25 +43,25 @@ will be overwritten.
43
43
  rake db:import
44
44
  ```
45
45
 
46
- This task will import a source db to a destination db. Tipical use is to import
47
- the production db into your development one.
46
+ **You will be prompted to choose the source and the target environment db**, and the
47
+ source db will be imported into the target db.
48
48
 
49
- You will be prompted to choose the source and the target environment db, and the
50
- source db will be imported into the target db. All environments containing the
49
+ This task will import a source db to a destination db. Tipical use is to import
50
+ the production db into your development one. All environments containing the
51
51
  string 'production' in their name are protected by default, which means you cannot
52
52
  overwrite them unless you explicitly override this setting in the override file
53
53
  (see next section for more info).
54
54
 
55
55
  #### BEWARE
56
56
 
57
- import process is destructive, be careful on what environment you choose to
58
- overwite. I take no responsibility for misuse or bugs in the code ;-)
57
+ **the import process is destructive** so be careful on which environment you
58
+ choose to overwite. I take no responsibility for misuse or bugs in the code ;-)
59
59
 
60
60
 
61
61
  #### Override database.yml
62
62
 
63
63
  Since some settings may be specific to the server environment (ie. host could
64
- be a private ip not reachable from anywhere) you can overwrite the settings in
64
+ be a private ip not reachable from elsewhere) you can override the settings in
65
65
  database.yml by adding a dbmanager_override.yml file in your rails config dir.
66
66
 
67
67
  You can also use this file to tell the dumper to ignore certain tables with
@@ -74,16 +74,17 @@ the ignoretables directive:
74
74
  - prods_view
75
75
  ```
76
76
 
77
- Another use is to set some environments as protected, or vice versa allow to
78
- overwrite production env.
79
- For example if we want to override the following setting, and make the database
77
+ Another use is to set some environment as protected, or on the other hand allow
78
+ overwriting if it's protected by default (ie. production env).
79
+
80
+ For example if you want to override the following setting, and make the database
80
81
  protected from overwriting:
81
82
 
82
83
  ```yaml
83
84
  beta:
84
85
  host: 192.168.0.1
85
86
  ```
86
- we should put in dbmanager_override.yml this:
87
+ you should put this in dbmanager_override.yml:
87
88
 
88
89
  ```yaml
89
90
  beta:
@@ -91,7 +92,7 @@ beta:
91
92
  protected: true
92
93
  ```
93
94
 
94
- Instead, if we want to make the production env writable we should add this:
95
+ Instead, if you want to make the production env writable you should add this:
95
96
 
96
97
  ```yaml
97
98
  production:
@@ -1,5 +1,11 @@
1
1
  module Dbmanager
2
- class AdapterError < StandardError
2
+ class EnvironmentProtectedError < StandardError
3
+ def initialize(message=nil)
4
+ super message || 'sorry the environment is protected from writing'
5
+ end
6
+ end
7
+
8
+ class MixedAdapterError < StandardError
3
9
  def initialize(message=nil)
4
10
  super message || 'You cannot mix different adapters!'
5
11
  end
@@ -37,6 +43,6 @@ require 'active_support/ordered_hash'
37
43
  require 'active_support/core_ext/enumerable'
38
44
  require 'active_support/core_ext/object/blank'
39
45
 
40
- %w[yml_parser adapters/mysql adapters/mysql2 runner importer dumper].each do |string|
46
+ %w[environment yml_parser adapters/mysql adapters/mysql2 runner importable dumpable].each do |string|
41
47
  require File.expand_path "../dbmanager/#{string}", __FILE__
42
48
  end
@@ -3,48 +3,19 @@ require 'time'
3
3
  module Dbmanager
4
4
  module Adapters
5
5
  module Mysql
6
- class EnvironmentProtectedError < StandardError
7
- def initialize(message=nil)
8
- super message || 'sorry the environment is protected from writing'
9
- end
10
- end
11
-
12
- class Connection
13
- attr_reader :environment
14
-
15
- delegate :host, :adapter, :database, :username, :password, :ignoretables,
16
- :encoding, :protected, :name, :port , :to => :environment
17
-
18
- def initialize(environment)
19
- @environment = environment
20
- end
21
-
22
- def params
23
- "-u#{username} #{flag :password, :p} #{flag :host, :h} #{flag :port, :P} #{database}"
24
- end
25
-
26
- def ignore_tables
27
- if ignoretables.present?
28
- ignoretables.inject('') do |s, view|
29
- s << " --ignore-table=#{database}.#{view}"
30
- end
31
- end
32
- end
33
-
34
- def flag(name, flag)
35
- send(name).present? ? "-#{flag}#{send(name)}" : ''
36
- end
37
-
38
- def protected?
39
- if name =~ /production/
40
- protected != false
41
- else
42
- protected == true
43
- end
6
+ module Connectable
7
+ def params(environment)
8
+ [ "-u#{environment.username}",
9
+ environment.flag(:password, :p),
10
+ environment.flag(:host, :h),
11
+ environment.flag(:port, :P),
12
+ environment.database
13
+ ].compact.join(' ')
44
14
  end
45
15
  end
46
16
 
47
17
  class Dumper
18
+ include Connectable
48
19
  attr_reader :source, :filename
49
20
 
50
21
  def initialize(source, filename)
@@ -57,38 +28,45 @@ module Dbmanager
57
28
  end
58
29
 
59
30
  def dump_command
60
- "mysqldump #{source.params} #{source.ignore_tables} > #{filename}"
31
+ "mysqldump #{ignoretables} #{params(source)} > #{filename}"
32
+ end
33
+
34
+ def ignoretables
35
+ if source.ignoretables.present?
36
+ source.ignoretables.inject [] do |arr, table|
37
+ arr << "--ignore-table=#{source.database}.#{table}"
38
+ end.join ' '
39
+ end
61
40
  end
62
41
  end
63
42
 
64
43
  class Importer
65
- attr_reader :source, :target
44
+ include Connectable
45
+ attr_reader :source, :target, :tmp_file
66
46
 
67
- def initialize(source, target)
68
- @source = source
69
- @target = target
47
+ def initialize(source, target, tmp_file)
48
+ @source = source
49
+ @target = target
50
+ @tmp_file = tmp_file
70
51
  end
71
52
 
72
53
  def run
73
- Dumper.new(source, temp_file).run
54
+ Dumper.new(source, tmp_file).run
74
55
  Dbmanager.execute! import_command
75
- remove_temp_file
56
+ ensure
57
+ remove_tmp_file
76
58
  end
77
59
 
78
60
  def import_command
79
61
  unless target.protected?
80
- "mysql #{target.params} < #{temp_file}"
62
+ "mysql #{params(target)} < #{tmp_file}"
81
63
  else
82
64
  raise EnvironmentProtectedError
83
65
  end
84
66
  end
85
67
 
86
- def remove_temp_file
87
- Dbmanager.execute "rm #{temp_file}"
88
- end
89
-
90
- def temp_file
91
- @temp_file ||= "/tmp/#{Time.now.strftime '%y%m%d%H%M%S'}"
68
+ def remove_tmp_file
69
+ Dbmanager.execute "rm #{tmp_file}"
92
70
  end
93
71
  end
94
72
  end
@@ -1,5 +1,4 @@
1
- # just the same as the mysql adapter, but ready for modifications
2
-
1
+ # just the same as the mysql adapter, but ready for future modifications
3
2
  module Dbmanager
4
3
  module Adapters
5
4
  module Mysql2
@@ -0,0 +1,40 @@
1
+ # Extends the runner with database dumping capabilities.
2
+ #
3
+ # The user will be prompted to enter the target filename path, pressing enter
4
+ # will set it to the default which is the value returned by #default_filename.
5
+ #
6
+ # The dump process happens in the #run method, and is eventually delegated to
7
+ # the specific database adapter which must implement the #run method.
8
+ module Dbmanager
9
+ module Dumpable
10
+ def self.extended(base)
11
+ class << base; attr_accessor :filename; end
12
+ end
13
+
14
+ def run
15
+ output.puts "\nPlease choose target file (defaults to #{default_filename}):\n\n"
16
+ @filename = get_filename
17
+ dumper.run
18
+ output.puts "Database successfully dumped in #{filename} file."
19
+ end
20
+
21
+ private
22
+
23
+ def dumper
24
+ adapter::Dumper.new(source, filename)
25
+ end
26
+
27
+ def adapter
28
+ Dbmanager::Adapters.const_get source.adapter.capitalize
29
+ end
30
+
31
+ def default_filename
32
+ Dbmanager.rails_root.join "tmp/#{source.database}.sql"
33
+ end
34
+
35
+ def get_filename
36
+ filename = input.gets.chomp
37
+ filename.blank? ? default_filename : Dbmanager.rails_root.join(filename)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ require 'ostruct'
2
+ # An +Environment+ object is created for each environment listed in the
3
+ # database.yml file.
4
+ #
5
+ # Common useful options are:
6
+ # +ignore_tables+: a list of tables that will not be dumped.
7
+ #
8
+ # +protected+: makes the environment protected from overwriting.
9
+ # By default every environment except for the ones that contain the
10
+ # +production+ string can be overwritten. This is dangerous of course, so you
11
+ # can protect an environment from overwriting adding +protected: true+ to
12
+ # that environment in the database.yml file.
13
+ # If on the other hand you want to be free to overwrite the production db
14
+ # you need to explicitly set +protected: false+ to that environment in the
15
+ # database.yml file.
16
+ module Dbmanager
17
+ class Environment < OpenStruct
18
+
19
+ # verifies whether the environment is protected from overwriting or not.
20
+ def protected?
21
+ if name =~ /production/
22
+ protected != false
23
+ else
24
+ protected == true
25
+ end
26
+ end
27
+
28
+ # returns the flag formatted for the requested attribute, if present.
29
+ # env = Environment.new(:password => 'secret')
30
+ # env.flag('password', 'p') # => -psecret
31
+ # env.flag('foo', 'f') # => nil
32
+ def flag(attribute, flag)
33
+ value = send attribute
34
+ "-#{flag}#{value}" if value.present?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ # Extends the runner with database importing capabilities.
2
+ #
3
+ # The import process happens in the #run method, and is eventually delegated to
4
+ # the specific database adapter which must implement the #run method. This
5
+ # adapter will receive the source and target environment plus the path for the
6
+ # sql dump file.
7
+ #
8
+ # The source and target environment must use the same adapter, ie you cannot
9
+ # import a mysql database on a sqlite3 database. For that purpose you can use
10
+ # the taps gem.
11
+ module Dbmanager
12
+ module Importable
13
+ def self.extended(base)
14
+ class << base; attr_reader :target; end
15
+ end
16
+
17
+ def run
18
+ @target = get_env('target')
19
+ execute_import
20
+ output.puts 'Database Import completed.'
21
+ end
22
+
23
+ def execute_import
24
+ adapter::Importer.new(source, target, tmp_file).run
25
+ end
26
+
27
+ def adapter
28
+ raise MixedAdapterError if source.adapter != target.adapter
29
+ Dbmanager::Adapters.const_get source.adapter.capitalize
30
+ end
31
+
32
+ def tmp_file
33
+ @tmp_file ||= File.join Dbmanager.rails_root, 'tmp', Time.now.strftime('%y%m%d%H%M%S')
34
+ end
35
+ end
36
+ end
@@ -1,34 +1,37 @@
1
+ # The runner main responsibility is to interact with the user in order to gather
2
+ # the information to accomplish the task.
3
+ #
4
+ # The runner object cannot do much when freshly instantiated, so for each kind
5
+ # of available task there is a corresponding module that can extend the runner
6
+ # so that it can accomplish its goal.
7
+ #
8
+ # Extension modules must define the #run method which contains the specific
9
+ # behaviour they provide.
1
10
  module Dbmanager
2
11
  class Runner
3
- attr_reader :input, :output, :environments, :source, :adapter
12
+ attr_reader :input, :output, :environments, :source
4
13
 
5
- def self.run
6
- new.run
14
+ def self.run(module_name)
15
+ runner = new
16
+ runner.extend Dbmanager.const_get(module_name.capitalize)
17
+ runner.run
7
18
  end
8
19
 
9
- def initialize(input, output)
20
+ def initialize(input=STDIN, output=STDOUT)
10
21
  @input = input
11
22
  @output = output
12
23
  @environments = YmlParser.environments
13
- @adapter = set_adapter
14
- @source = adapter::Connection.new(set_source)
24
+ @source = get_env
15
25
  end
16
26
 
17
- def set_adapter
18
- adapters = environments.map {|name, env| env.adapter}.uniq
19
- if adapters.size > 1
20
- raise AdapterError
21
- else
22
- Dbmanager::Adapters.const_get adapters.first.capitalize
23
- end
27
+ def get_env(type='source')
28
+ output.puts "\nPlease choose #{type} db:\n\n"
29
+ get_environment
24
30
  end
25
31
 
26
- def set_source
27
- output.puts "\nPlease choose source db:\n\n"
28
- get_env
29
- end
32
+ private
30
33
 
31
- def get_env
34
+ def get_environment
32
35
  environments.keys.each_with_index do |name, i|
33
36
  output.puts "#{i+1}) #{name}"
34
37
  end
@@ -1,3 +1,3 @@
1
1
  module Dbmanager
2
- VERSION = "0.0.6"
2
+ VERSION = '0.1.0'
3
3
  end
@@ -1,12 +1,9 @@
1
1
  require 'erb'
2
2
  require 'yaml'
3
- require 'ostruct'
4
3
  require 'active_support/core_ext/hash'
5
4
 
6
5
  module Dbmanager
7
6
  module YmlParser
8
- class Environment < OpenStruct; end
9
-
10
7
  extend self
11
8
  attr_writer :config
12
9
 
@@ -1,11 +1,11 @@
1
1
  namespace :db do
2
2
  desc 'import specific environment db data into another environment db'
3
3
  task :import do
4
- Dbmanager::Importer.run
4
+ Dbmanager::Runner.run('importable')
5
5
  end
6
6
 
7
7
  desc 'dump specific environment db data in tmp directory'
8
8
  task :dump do
9
- Dbmanager::Dumper.run
9
+ Dbmanager::Runner.run('dumpable')
10
10
  end
11
11
  end
@@ -1,10 +1,6 @@
1
1
  module Dbmanager
2
2
  module Adapters
3
3
  module SomeAdapter
4
- class Connection
5
- def initialize(*args); end
6
- end
7
-
8
4
  class Dumper
9
5
  def initialize(*args); end
10
6
 
@@ -3,16 +3,13 @@ development:
3
3
  database: demo_development
4
4
  encoding: utf8
5
5
  username: root
6
- password: devil
7
-
8
- # ale i tuoi settaggi specifici devi metterli in config/dbloginyml, non qui
9
- # socket: /Applications/MAMP/tmp/mysql/mysql.sock
6
+ password: secret
10
7
 
11
8
  beta:
12
9
  adapter: mysql
13
10
  database: demo_beta
14
- username: beta_username
15
- password: asdasd
11
+ username: beta_user
12
+ password: beta_pass
16
13
  port: 3306
17
14
  host: 123.123.123.123
18
15
  encoding: utf8
@@ -20,26 +17,21 @@ beta:
20
17
  production:
21
18
  adapter: mysql
22
19
  database: demo_production
23
- username: production_username
24
- password: asdasd
20
+ username: prod_user
21
+ password: prod_pass
25
22
  port: 3306
26
23
  host: 123.123.123.123
27
24
  encoding: utf8
28
25
 
29
26
  test:
30
- adapter: mysql
27
+ adapter: sqlite3
31
28
  database: demo_test
32
- encoding: utf8
33
- port: 3306
34
- host: 345.345.345.345
35
- username: root
36
- password: devil
37
29
 
38
30
  shop:
39
31
  adapter: mysql
40
32
  database: demo_shop
41
- username: demo_username
42
- password: asdasd
33
+ username: demo_user
34
+ password: demo_pass
43
35
  port: 3306
44
36
  host: 123.123.123.123
45
37
  encoding: utf8
@@ -2,12 +2,4 @@ beta:
2
2
  host: 345.345.345.345
3
3
  protected: true
4
4
  ignoretables:
5
- - view0
6
-
7
- production:
8
- protected: false
9
-
10
- test:
11
- ignoretables:
12
- - view0
13
- - view1
5
+ - some_view
@@ -3,93 +3,64 @@ require 'spec_helper'
3
3
  module Dbmanager
4
4
  module Adapters
5
5
  module Mysql
6
- describe Connection do
7
- before { stub_rails_root }
8
-
9
- describe 'a mysql adapter instance' do
10
- subject { Connection.new Dbmanager::YmlParser.environments['test'] }
11
-
12
- it 'delegates to environment object' do
13
- subject.host.should == subject.environment.host
14
- end
15
-
16
- describe '#params' do
17
- it 'returns expected string' do
18
- subject.params.should == '-uroot -pdevil -h345.345.345.345 -P3306 demo_test'
19
- end
20
- end
6
+ describe Dumper do
7
+ let :source do
8
+ Environment.new(
9
+ :username => 'root',
10
+ :ignoretables => ['a_view', 'another_view'],
11
+ :database => 'database',
12
+ :password => 'secret',
13
+ :port => 42,
14
+ :host => '0.0.0.0'
15
+ )
16
+ end
21
17
 
22
- describe '#ignore_tables' do
23
- context 'when there are tables to be skipped' do
24
- it 'returns expected string' do
25
- subject.ignore_tables.should == ' --ignore-table=demo_test.view0 --ignore-table=demo_test.view1'
26
- end
27
- end
18
+ subject { Dumper.new(source, '/tmp/dump_file.sql') }
28
19
 
29
- context 'when there are no tables to be skipped' do
30
- it 'returns nil' do
31
- subject.stub!(:ignoretables => nil)
32
- subject.ignore_tables.should be_nil
33
- end
20
+ describe '#ignoretables' do
21
+ context 'when there are tables to be ignored' do
22
+ it 'returns a string containing ignore-table flags' do
23
+ string = '--ignore-table=database.a_view --ignore-table=database.another_view'
24
+ subject.ignoretables.should == string
34
25
  end
35
26
  end
36
27
 
37
- describe '#protected?' do
38
- it 'is false by default' do
39
- subject.should_not be_protected
40
- end
41
-
42
- context 'when name matches production string' do
43
- it 'is true by default ' do
44
- subject.stub! :name => 'production-merge'
45
- subject.should be_protected
46
- end
47
-
48
- context 'when protected is set to false' do
49
- it 'is false' do
50
- subject.stub! :name => 'production', :protected => false
51
- subject.should_not be_protected
52
- end
53
- end
28
+ context 'when there are no tables to be ignored' do
29
+ it 'returns nil' do
30
+ source.stub!(:ignoretables => nil)
31
+ subject.ignoretables.should be_nil
54
32
  end
55
33
  end
34
+ end
56
35
 
57
- describe '#flag' do
58
- context 'when requested flag has a value' do
59
- it 'returns expected string' do
60
- subject.flag(:password, :p).should == '-pdevil'
61
- end
62
- end
63
-
64
- context 'when requested flag has no value' do
65
- it 'returns a blank string' do
66
- subject.stub!(:password => nil)
67
- subject.flag(:password, :p).should == ''
68
- end
69
- end
36
+ describe '#dump_command' do
37
+ it 'returns expected command' do
38
+ command = [
39
+ 'mysqldump --ignore-table=database.a_view',
40
+ '--ignore-table=database.another_view -uroot',
41
+ '-psecret -h0.0.0.0 -P42 database > /tmp/dump_file.sql'
42
+ ].join(' ')
43
+ subject.dump_command.should == command
70
44
  end
71
45
  end
72
46
  end
73
47
 
74
48
  describe Importer do
75
49
  describe 'an importer instance' do
76
- before { Time.stub! :now => Time.parse('2012/03/23 12:30:32') }
77
- let(:target) { mock :params => 'target-params', :protected? => false, :name => 'beta' }
78
- let(:source) { mock :params => 'source-params', :protected? => false, :name => 'development' }
79
- subject { Importer.new source, target }
50
+ before { Time.stub! :now => Time.parse('2012/03/23 12:30:32') }
51
+ let(:target) { Environment.new :protected => false, :name => 'beta', :username => 'beta_user' }
52
+ let(:source) { Environment.new :protected => false, :name => 'development', :username => 'root' }
53
+ let(:tmp_file) { '/some/arbitrary/path' }
54
+ subject { Importer.new source, target, tmp_file }
80
55
 
81
56
  it 'has target and source attribute methods' do
82
- %w[source target].each { |m| subject.should respond_to(m) }
83
- end
84
-
85
- it 'has a timestamped temporary file' do
86
- subject.temp_file.should == '/tmp/120323123032'
57
+ %w[source target tmp_file].each { |m| subject.should respond_to m }
87
58
  end
88
59
 
89
60
  describe '#import_command' do
90
61
  context 'when environment is not protected' do
91
62
  it 'returns expected command' do
92
- subject.import_command.should == 'mysql target-params < /tmp/120323123032'
63
+ subject.import_command.should == 'mysql -ubeta_user < /some/arbitrary/path'
93
64
  end
94
65
  end
95
66
 
@@ -101,10 +72,10 @@ module Dbmanager
101
72
  end
102
73
  end
103
74
 
104
- describe '#remove_temp_file' do
75
+ describe '#remove_tmp_file' do
105
76
  it 'tries to remove the temporary file' do
106
- Dbmanager.should_receive(:execute).with("rm #{subject.temp_file}")
107
- subject.remove_temp_file
77
+ Dbmanager.should_receive(:execute).with("rm #{subject.tmp_file}")
78
+ subject.remove_tmp_file
108
79
  end
109
80
  end
110
81
 
@@ -117,29 +88,13 @@ module Dbmanager
117
88
 
118
89
  it 'imports the db' do
119
90
  Dumper.stub! :new => mock.as_null_object
120
- subject.stub!(:remove_temp_file => true)
91
+ subject.stub!(:remove_tmp_file => true)
121
92
  Dbmanager.should_receive(:execute!).with(subject.import_command)
122
93
  subject.run
123
94
  end
124
95
  end
125
96
  end
126
97
  end
127
-
128
- describe Dumper do
129
- subject do
130
- Dumper.new(
131
- mock(:params => 'source-params', :ignore_tables => '--ignore-table=view'),
132
- '/tmp/dump_file.sql'
133
- )
134
- end
135
-
136
- describe '#dump_command' do
137
- it 'returns expected command' do
138
- command = 'mysqldump source-params --ignore-table=view > /tmp/dump_file.sql'
139
- subject.dump_command.should == command
140
- end
141
- end
142
- end
143
98
  end
144
99
  end
145
100
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Dbmanager do
4
4
  describe '#rails_root' do
5
- it 'should wrap Rails.root' do
5
+ it 'wraps Rails.root' do
6
6
  Rails = mock unless defined? Rails
7
7
  Rails.should_receive :root
8
8
  Dbmanager.rails_root
@@ -10,7 +10,7 @@ describe Dbmanager do
10
10
  end
11
11
 
12
12
  describe '#execute' do
13
- it 'execute a system command' do
13
+ it 'executes a system command' do
14
14
  Dbmanager.should_receive(:system)
15
15
  Dbmanager.execute('echo')
16
16
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Dbmanager
4
+ describe Dumpable do
5
+ subject do
6
+ Object.new.tap {|o| o.extend Dumpable}
7
+ end
8
+
9
+ before do
10
+ subject.stub :output => STDStub.new, :input => STDStub.new
11
+ end
12
+
13
+ describe '#run' do
14
+ before do
15
+ subject.stub(
16
+ :get_filename => 'filename',
17
+ :default_filename => 'defaultname',
18
+ :dumper => mock.as_null_object
19
+ )
20
+ end
21
+
22
+ it 'sends expected output' do
23
+ subject.run
24
+ [
25
+ 'Please choose target file (defaults to defaultname):',
26
+ 'Database successfully dumped in filename file.'
27
+ ].each do |message|
28
+ subject.output.content.should include(message)
29
+ end
30
+ end
31
+
32
+ it 'delegates the actual dumping to the dumper' do
33
+ subject.send(:dumper).should_receive(:run)
34
+ subject.run
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ module Dbmanager
4
+ describe Environment do
5
+ describe 'a generic environment' do
6
+ subject { Environment.new :name => 'beta' }
7
+
8
+ it { subject.should_not be_protected }
9
+
10
+ context 'when the protected attribute is changed to true' do
11
+ before { subject.protected = true }
12
+
13
+ it { subject.should be_protected }
14
+ end
15
+ end
16
+
17
+ describe 'the production environment' do
18
+ subject { Environment.new(:name => 'production') }
19
+
20
+ it { subject.should be_protected }
21
+
22
+ context 'when the protected attribute is explicitly set to false' do
23
+ before { subject.protected = false }
24
+
25
+ it { subject.should_not be_protected }
26
+ end
27
+ end
28
+
29
+ describe '#flag' do
30
+ context 'when requested attribute is present' do
31
+ before { subject.stub(:password => 'secret') }
32
+
33
+ it 'returns a string containing the expected flag' do
34
+ subject.flag(:password, :p).should == '-psecret'
35
+ end
36
+ end
37
+
38
+ context 'when the requested attribute is not present' do
39
+ it 'returns nil' do
40
+ subject.flag(:foo, :p).should be_nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ module Dbmanager
4
+ describe Importable do
5
+ subject do
6
+ Object.new.tap {|o| o.extend Importable}
7
+ end
8
+
9
+ before do
10
+ stub_rails_root
11
+ subject.stub :output => STDStub.new, :input => STDStub.new, :get_env => nil
12
+ end
13
+
14
+ it 'has target attribute reader' do
15
+ subject.instance_eval { @target = 'something'}
16
+ subject.target.should == 'something'
17
+ end
18
+
19
+ context 'when source and target have same adapter' do
20
+ before do
21
+ subject.stub(
22
+ :source => mock(:adapter => 'mysql2'),
23
+ :target => mock(:adapter => 'mysql2')
24
+ )
25
+ end
26
+
27
+ it 'uses the expected adapter' do
28
+ subject.adapter.should == Dbmanager::Adapters::Mysql2
29
+ end
30
+
31
+ it 'delegates importing process to the adapter importer' do
32
+ adapter_importer = Dbmanager::Adapters::Mysql2::Importer
33
+ adapter_importer.should_receive(:new).and_return mock.as_null_object
34
+ subject.run
35
+ end
36
+ end
37
+
38
+ context 'when source and target adapters differ' do
39
+ before do
40
+ subject.stub(
41
+ :source => mock(:adapter => 'sqlite3'),
42
+ :target => mock(:adapter => 'mysql2')
43
+ )
44
+ end
45
+
46
+ it 'adapter raises MixedAdapterError' do
47
+ expect {subject.adapter}.to raise_error(MixedAdapterError)
48
+ end
49
+ end
50
+
51
+ describe '#run' do
52
+ it 'outputs expected messages' do
53
+ subject.stub(:execute_import => nil)
54
+ subject.run
55
+ message = 'Database Import completed.'
56
+ subject.output.content.should include(message)
57
+ end
58
+ end
59
+
60
+ describe '#tmp_file' do
61
+ it 'includes expected path' do
62
+ Time.stub :now => Time.parse('1974/09/20 14:12:33')
63
+ subject.tmp_file.should =~ Regexp.new('dbmanager/spec/fixtures/tmp/740920141233')
64
+ end
65
+ end
66
+ end
67
+ end
@@ -3,68 +3,41 @@ require 'fixtures/adapter_sample'
3
3
 
4
4
  module Dbmanager
5
5
  describe Runner do
6
- let(:input) { STDStub.new }
6
+ let(:envs) { [mock] }
7
+ let(:input) { STDStub.new }
7
8
  let(:output) { STDStub.new }
8
9
 
9
- describe '#initialize' do
10
- let(:envs) { [mock] }
10
+ before do
11
+ YmlParser.stub!(:environments => envs)
12
+ Runner.any_instance.stub(:get_environment => envs.first)
13
+ end
11
14
 
15
+ describe '#initialize' do
12
16
  subject { Runner.new(input, output) }
13
17
 
14
- before do
15
- YmlParser.stub!(:environments => envs)
16
- Runner.any_instance.stub(:set_adapter => Adapters::SomeAdapter, :set_source => nil)
17
- end
18
-
19
18
  it 'sets expected attributes' do
20
19
  subject.input.should == input
21
20
  subject.output.should == output
22
21
  subject.environments.should == envs
23
- subject.adapter.should == Adapters::SomeAdapter
24
- subject.source.should be_a(Adapters::SomeAdapter::Connection)
22
+ subject.source.should == envs.first
25
23
  end
26
24
  end
27
25
 
28
- describe '#set_adapter' do
26
+ describe '#get_env' do
29
27
  subject { Runner.new(input, output) }
30
28
 
31
- before { Runner.any_instance.stub(:set_source => nil) }
32
-
33
- context 'when different adapters are mixed' do
34
- it 'raises an error' do
35
- envs = {:beta => mock(:adapter => 'Mysql'), :development => mock(:adapter => 'Sqlite3')}
36
- subject.stub!(:environments => envs)
37
- expect { subject.set_adapter }.to raise_error(AdapterError)
38
- end
39
- end
40
-
41
- context 'when there is only one kind of adapter' do
42
- it 'returns an adapter class' do
43
- envs = {:beta => mock(:adapter => 'Mysql'), :development => mock(:adapter => 'Mysql')}
44
- subject.instance_variable_set '@environments', envs
45
- Dbmanager::Adapters.should_receive(:const_get).and_return(Adapters::SomeAdapter)
46
- subject.set_adapter.should == Adapters::SomeAdapter
47
- end
29
+ it 'outputs default message' do
30
+ subject.get_env
31
+ output.content.should include('Please choose source db:')
48
32
  end
49
33
 
50
- context 'when the adapter is mysql2' do
51
- it 'returns the correct adapter class' do
52
- envs = {:development => mock(:adapter => 'mysql2')}
53
- subject.instance_variable_set '@environments', envs
54
- subject.set_adapter.should == Adapters::Mysql2
55
- end
34
+ it 'outputs expected message' do
35
+ subject.get_env('target')
36
+ output.content.should include('Please choose target db:')
56
37
  end
57
- end
58
-
59
- describe '#set_source' do
60
- subject { Runner.new(input, output) }
61
-
62
- before { Runner.any_instance.stub(:set_adapter => Adapters::SomeAdapter) }
63
38
 
64
- it 'outputs expected message' do
65
- Runner.any_instance.stub(:get_env => nil)
66
- subject.set_source
67
- output.content.should include('Please choose source db:')
39
+ it 'returns the chosen environment' do
40
+ subject.get_env.should == envs.first
68
41
  end
69
42
  end
70
43
  end
@@ -52,12 +52,12 @@ module Dbmanager
52
52
  end
53
53
 
54
54
  it 'removes old unchanged settings' do
55
- YmlParser.config['beta']['username'].should == 'beta_username'
55
+ YmlParser.config['beta']['username'].should == 'beta_user'
56
56
  end
57
57
 
58
58
  context 'when the environment has a ignoretables directive' do
59
59
  it 'should populate ignoretables with the expected array' do
60
- YmlParser.config['beta']['ignoretables'].should == ['view0']
60
+ YmlParser.config['beta']['ignoretables'].should == ['some_view']
61
61
  end
62
62
  end
63
63
  end
metadata CHANGED
@@ -1,74 +1,71 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: dbmanager
3
- version: !ruby/object:Gem::Version
4
- hash: 19
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 6
10
- version: 0.0.6
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - andrea longhi
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-05-10 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: rspec
36
23
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
38
25
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
46
38
  type: :development
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: rake
50
39
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
52
41
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
60
54
  type: :development
61
- version_requirements: *id003
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
62
  description: helps manage db dumps and imports via rake tasks
63
- email:
63
+ email:
64
64
  - andrea.longhi@mikamai.com
65
65
  executables: []
66
-
67
66
  extensions: []
68
-
69
67
  extra_rdoc_files: []
70
-
71
- files:
68
+ files:
72
69
  - .gitignore
73
70
  - CHANGELOG.md
74
71
  - Gemfile
@@ -79,8 +76,9 @@ files:
79
76
  - lib/dbmanager.rb
80
77
  - lib/dbmanager/adapters/mysql.rb
81
78
  - lib/dbmanager/adapters/mysql2.rb
82
- - lib/dbmanager/dumper.rb
83
- - lib/dbmanager/importer.rb
79
+ - lib/dbmanager/dumpable.rb
80
+ - lib/dbmanager/environment.rb
81
+ - lib/dbmanager/importable.rb
84
82
  - lib/dbmanager/runner.rb
85
83
  - lib/dbmanager/version.rb
86
84
  - lib/dbmanager/yml_parser.rb
@@ -92,53 +90,46 @@ files:
92
90
  - spec/fixtures/config/dbmanager_override.yml
93
91
  - spec/lib/adapters/mysql_spec.rb
94
92
  - spec/lib/dbmanager_spec.rb
95
- - spec/lib/dumper_spec.rb
96
- - spec/lib/importer_spec.rb
93
+ - spec/lib/dumpable_spec.rb
94
+ - spec/lib/environment_spec.rb
95
+ - spec/lib/importable_spec.rb
97
96
  - spec/lib/runner_spec.rb
98
97
  - spec/lib/yml_parser_spec.rb
99
98
  - spec/spec_helper.rb
100
99
  - spec/support/std_stub.rb
101
- homepage: ""
100
+ homepage: ''
102
101
  licenses: []
103
-
104
102
  post_install_message:
105
103
  rdoc_options: []
106
-
107
- require_paths:
104
+ require_paths:
108
105
  - lib
109
- required_ruby_version: !ruby/object:Gem::Requirement
106
+ required_ruby_version: !ruby/object:Gem::Requirement
110
107
  none: false
111
- requirements:
112
- - - ">="
113
- - !ruby/object:Gem::Version
114
- hash: 3
115
- segments:
116
- - 0
117
- version: "0"
118
- required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
113
  none: false
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- hash: 3
124
- segments:
125
- - 0
126
- version: "0"
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
127
118
  requirements: []
128
-
129
119
  rubyforge_project: dbmanager
130
120
  rubygems_version: 1.8.24
131
121
  signing_key:
132
122
  specification_version: 3
133
123
  summary: database manager
134
- test_files:
124
+ test_files:
135
125
  - spec/fixtures/adapter_sample.rb
136
126
  - spec/fixtures/config/database.yml
137
127
  - spec/fixtures/config/dbmanager_override.yml
138
128
  - spec/lib/adapters/mysql_spec.rb
139
129
  - spec/lib/dbmanager_spec.rb
140
- - spec/lib/dumper_spec.rb
141
- - spec/lib/importer_spec.rb
130
+ - spec/lib/dumpable_spec.rb
131
+ - spec/lib/environment_spec.rb
132
+ - spec/lib/importable_spec.rb
142
133
  - spec/lib/runner_spec.rb
143
134
  - spec/lib/yml_parser_spec.rb
144
135
  - spec/spec_helper.rb
@@ -1,31 +0,0 @@
1
- module Dbmanager
2
- class Dumper < Runner
3
- attr_reader :filename
4
-
5
- def initialize(input=STDIN, output=STDOUT)
6
- super
7
- @filename = set_filename
8
- end
9
-
10
- def run
11
- adapter::Dumper.new(source, filename).run
12
- output.puts "Database Dump completed to #{filename}"
13
- end
14
-
15
- private
16
-
17
- def set_filename
18
- output.puts "\nPlease choose target file (defaults to #{default_filename})\n\n"
19
- get_filename
20
- end
21
-
22
- def default_filename
23
- "#{Dbmanager.rails_root.join 'tmp', "#{source.database}.sql"}"
24
- end
25
-
26
- def get_filename
27
- filename = input.gets.chomp
28
- filename.blank? ? default_filename : Dbmanager.rails_root.join(filename)
29
- end
30
- end
31
- end
@@ -1,22 +0,0 @@
1
- module Dbmanager
2
- class Importer < Runner
3
- attr_reader :target
4
-
5
- def initialize(input=STDIN, output=STDOUT)
6
- super
7
- @target = adapter::Connection.new(set_target)
8
- end
9
-
10
- def run
11
- adapter::Importer.new(source, target).run
12
- output.puts 'Database Import completed.'
13
- end
14
-
15
- private
16
-
17
- def set_target
18
- output.puts "\nPlease choose target db:\n\n"
19
- get_env
20
- end
21
- end
22
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
- require 'fixtures/adapter_sample'
3
-
4
- module Dbmanager
5
- describe Dumper do
6
- describe '#run' do
7
- let(:input) { STDStub.new }
8
- let(:output) { STDStub.new }
9
-
10
- subject { Dumper.new(input, output) }
11
-
12
- before do
13
- stub_rails_root
14
- input.stub!(:gets => mock.as_null_object)
15
- Dumper.any_instance.stub(
16
- :set_source => nil,
17
- :adapter => Adapters::SomeAdapter,
18
- :default_filename => 'default_filename'
19
- )
20
- end
21
-
22
- it 'dumps a db' do
23
- Adapters::SomeAdapter::Dumper.should_receive(:new).and_return(mock(:run => nil))
24
- subject.run
25
- end
26
- end
27
- end
28
- end
@@ -1,24 +0,0 @@
1
- require 'spec_helper'
2
- require 'fixtures/adapter_sample'
3
-
4
- module Dbmanager
5
- describe Importer do
6
- describe '#run' do
7
- let(:input) { STDStub.new }
8
- let(:output) { STDStub.new }
9
-
10
- subject { Importer.new(input, output) }
11
-
12
- before do
13
- stub_rails_root
14
- input.stub!(:gets => "1\n")
15
- Importer.any_instance.stub(:adapter => Adapters::SomeAdapter)
16
- end
17
-
18
- it 'imports a db' do
19
- Adapters::SomeAdapter::Importer.should_receive(:new).and_return(mock(:run => nil))
20
- subject.run
21
- end
22
- end
23
- end
24
- end