database_sanitizer 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0ae899e9c69e083b9ad8adb9f427a384c898621d
4
+ data.tar.gz: 704c9bb2b7ee445b459078edf86fd6198023cd28
5
+ SHA512:
6
+ metadata.gz: 0045968c62ea497b1ba352b60c5eb58c629ce2e1fcaf5480f73afabd68c8a8ba234b7a1e62a16e3563533a9e4d4e8f0fc54446af7efb09c6f0a57b6a62306d09
7
+ data.tar.gz: c1ebeac6a04345da7edbef0cffb4beee17276e47d6bdd8add408f1a6ec9a7e4c31beac21a197667c369eac31773857996758e3899a9a87f9891da0260c4f88be
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in database_exporter.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'pry'
8
+ gem 'rspec'
9
+ end
10
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Marton Somogyi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # DatabaseExporter
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'database_exporter'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install database_exporter
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/database_exporter/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ require 'yaml'
3
+ require 'optparse'
4
+
5
+ require 'database_sanitizer'
6
+
7
+ ENV['SOURCE'] ||= 'postgres'
8
+ ENV['TARGET'] ||= "#{ENV['SOURCE']}_sanitized"
9
+
10
+ options = {dbconf: File.expand_path('config/database.yml', Dir.pwd)}
11
+ OptionParser.new do |opts|
12
+ opts.on('-t', '--tables TABLES', Array, 'Restrict export scope to these tables') { |tables| options[:tables] = tables }
13
+ opts.on('-e', '--exclude EXCLUDE_TABLES', Array, 'Exclude these tables') { |tables| options[:exclude_tables] = tables }
14
+ opts.on('-r', '--transformers TRANSFORMERS', 'Ruby module containing custom transformer definitions') { |trans| options[:transformers] = trans }
15
+ opts.on('--conf DBCONF', 'Database config YAML') { |dbconf| options[:dbconf] = dbconf }
16
+ opts.on('--schema SCHEMA', 'Database schema from `rake db:schema:dump`') { |schema| options[:schema] = schema }
17
+ end.parse!
18
+
19
+ if options[:transformers]
20
+ begin require File.expand_path(options[:transformers], Dir.pwd)
21
+ rescue LoadError; puts $!
22
+ end
23
+ end
24
+
25
+ DBCONF = YAML::load IO.read options[:dbconf] rescue abort "Error reading #{options[:dbconf]}: #{$!}"
26
+
27
+ begin
28
+ db = ENV['SOURCE']
29
+ DatabaseSanitizer::Source.establish_connection(DBCONF[db]).connection
30
+ db = ENV['TARGET']
31
+ ActiveRecord::Base.establish_connection(DBCONF[db]).connection
32
+ rescue StandardError
33
+ abort "Couldn't connect to #{options[:dbconf]}[#{db}]: #{$!}"
34
+ end
35
+
36
+ DatabaseSanitizer.export DatabaseSanitizer::Source.connection, ActiveRecord::Base.connection, tables: options[:tables], exclude: options[:exclude_tables], schema: options[:schema]
37
+
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ require File.expand_path('../lib/database_sanitizer/version', __FILE__)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'database_sanitizer'
6
+ spec.version = DatabaseSanitizer::VERSION
7
+ spec.authors = ['Marton Somogyi']
8
+ spec.email = ['msomogyi@whitepages.com']
9
+ spec.summary = %q{Export your SQL database}
10
+ spec.description = %q{Duplicate a databse with sanitization options using SQL comments}
11
+ spec.homepage = 'https://github.com/mcbuddha/database_sanitizer'
12
+ spec.license = 'MIT'
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_development_dependency 'bundler', '~> 1.6'
20
+ spec.add_development_dependency 'rake', '~> 10'
21
+ spec.add_development_dependency 'pg', '~> 0.17'
22
+
23
+ spec.add_runtime_dependency 'activerecord', '~> 3'
24
+ spec.add_runtime_dependency 'activerecord-comments', '~> 0'
25
+ spec.add_runtime_dependency 'progress', '~> 3'
26
+ spec.add_runtime_dependency 'iconv', '~> 1'
27
+ end
@@ -0,0 +1,10 @@
1
+ module DatabaseSanitizer
2
+ Transformers = {
3
+ 'email' => ->(i, rec) { "email#{i.to_s.rjust(5, ?0)}@#{rec.split(?@)[1]}"},
4
+ 'wipe' => proc { nil },
5
+ 'zero' => proc { 0 },
6
+ 'empty_string' => proc { '' },
7
+ 'name' => proc { 'John Doe' },
8
+ 'phone_number' => ->(i, rec) { rec.nil? ? rec : "#{rec[0,3]}#{i.to_s.rjust rec.length-3, ?0}" }
9
+ }
10
+ end
@@ -0,0 +1,3 @@
1
+ module DatabaseSanitizer
2
+ VERSION = '0.0.6'
3
+ end
@@ -0,0 +1,66 @@
1
+ require 'database_sanitizer/version'
2
+ require 'active_record/comments'
3
+ require 'progress'
4
+
5
+ module DatabaseSanitizer
6
+ class Source < ActiveRecord::Base
7
+ end
8
+ end
9
+
10
+ require 'database_sanitizer/transformers'
11
+
12
+ module DatabaseSanitizer
13
+ class << self
14
+ def extract_transformer comment; comment ? comment[/sanitize: ?(\w+)/,1] : nil; end
15
+
16
+ def read_comments conn, tables
17
+ tables.inject({}) do |transformers, table|
18
+ transformers[table.to_sym] = conn.retrieve_column_comments(table.to_sym).inject({}) do |table_transformers, column|
19
+ transformer_key = extract_transformer column[1]
20
+ unless transformer_key.nil? || Transformers.include?(transformer_key)
21
+ abort "Transformer '#{transformer_key}' not found (#{table}.#{column[0]})"
22
+ end
23
+ table_transformers[column[0]] = transformer_key && Transformers[transformer_key]
24
+ table_transformers
25
+ end
26
+ transformers
27
+ end
28
+ end
29
+
30
+ def duplicate_schema schema=nil
31
+ schema_src = nil
32
+ if schema.nil?
33
+ schema_sio = StringIO.new
34
+ puts 'Dumping schema.rb...'
35
+ ActiveRecord::SchemaDumper.dump(Source.connection, schema_sio)
36
+ puts 'Loading schema.rb...'
37
+ ActiveRecord::Migration.suppress_messages { eval schema_sio.string }
38
+ else
39
+ puts 'Reading schema SQL...'
40
+ schema_src = IO.read File.expand_path(schema, Dir.pwd)
41
+ ActiveRecord::Migration.suppress_messages { ActiveRecord::Base.connection.exec_query schema_src }
42
+ end
43
+ end
44
+
45
+ def export src, dest, opts={}
46
+ duplicate_schema opts[:schema]
47
+ tables = (opts[:tables] || src.tables.collect(&:to_s)) - (opts[:exclude] || [])
48
+ transformers = read_comments dest, tables
49
+
50
+ max_tbl_name_len = transformers.keys.map(&:length).sort.last || 0
51
+ tables.with_progress('Exporting').each do |table|
52
+ result = src.exec_query "SELECT * FROM #{table}"
53
+ cols = result.columns.join ','
54
+ dest.transaction do
55
+ result.rows.with_progress(table.rjust max_tbl_name_len).each_with_index do |src_row, row_i|
56
+ values = result.columns.each_with_index.map do |col, col_i|
57
+ transformer = transformers[table.to_sym][col.to_sym]
58
+ dest.quote transformer ? transformer.(row_i, src_row[col_i]) : src_row[col_i]
59
+ end
60
+ dest.insert_sql "INSERT INTO #{dest.quote_table_name table} (#{cols}) VALUES (#{values.join ','})"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,18 @@
1
+ postgres:
2
+ adapter: postgresql
3
+ database: database_exporter_test
4
+ host: 127.0.0.1
5
+ username: postgres
6
+ password: postgres
7
+
8
+ mysql:
9
+ adapter: mysql2
10
+ database: database_exporter_test
11
+ user: root
12
+ password: password
13
+
14
+ sqlite:
15
+ adapter: sqlite3
16
+ database: test/db/database_exporter_test
17
+ pool: 5
18
+ timeout: 5000
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe DatabaseExporter do
4
+ describe '#extract_transformer', nodb: true do
5
+ context 'should return nil for no transformer' do
6
+ ['no tag comment', nil, '', 'sanitize no tag'].each do |comment|
7
+ it { expect(described_class.extract_transformer comment).to be_nil }
8
+ end
9
+ end
10
+
11
+ context 'should return transformer' do
12
+ [
13
+ 'sanitize: test_tr',
14
+ 'random sanitize: test_tr comment',
15
+ 'some sanitize: test_tr, sanitize: other',
16
+ 'without sanitize:test_tr space',
17
+ 'trailing sanitize: test_tr'
18
+ ].each do |comment|
19
+ it { expect(described_class.extract_transformer comment).to eq('test_tr') }
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#read_comments' do
25
+ before do
26
+ ActiveRecord::Migration.suppress_messages do
27
+ ActiveRecord::Schema.define do
28
+ change_table :test do |t|
29
+ t.string :field3
30
+ t.string :field4
31
+ end
32
+ end
33
+ end
34
+ comments = {
35
+ field1: 'comment no tag',
36
+ field2: nil,
37
+ field3: 'comment sanitize: name',
38
+ field4: 'sanitize:email'
39
+ }.each { |col, com| ActiveRecord::Base.connection.set_column_comment :test, col, com }
40
+ end
41
+
42
+ context 'some defined' do
43
+ it 'should get transformers' do
44
+ transformers = described_class.read_comments(ActiveRecord::Base.connection, [:test])[:test]
45
+ expect(transformers[:field1]).to be_nil
46
+ expect(transformers[:field2]).to be_nil
47
+ expect(transformers[:field3]).to be_kind_of(Proc)
48
+ expect(transformers[:field4]).to be_kind_of(Proc)
49
+ end
50
+ end
51
+
52
+ context 'some undefined' do
53
+ before { ActiveRecord::Base.connection.set_column_comment :test, :field2, 'sanitize:undef' }
54
+ it 'should abort' do
55
+ expect(lambda {described_class.read_comments ActiveRecord::Base.connection, [:test]}).to raise_error(SystemExit)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,28 @@
1
+ $: << File.expand_path('../lib', __FILE__)
2
+
3
+ require 'yaml'
4
+ require 'pry'
5
+
6
+ require 'database_exporter'
7
+
8
+ DBCONF = YAML::load(IO.read(File.expand_path('../config/database.yml', __FILE__)))
9
+ ENV['DB'] ||= 'postgres'
10
+ ActiveRecord::Base.establish_connection DBCONF[ENV['DB']]
11
+
12
+ RSpec.configure do |c|
13
+ c.around(:each) do |ex|
14
+ unless ex.metadata[:nodb]
15
+ ActiveRecord::Migration.suppress_messages do
16
+ ActiveRecord::Schema.define do
17
+ create_table :test do |t|
18
+ t.string :field1
19
+ t.integer :field2
20
+ end
21
+ end
22
+ end
23
+ end
24
+ ex.run
25
+ ActiveRecord::Migration.suppress_messages { ActiveRecord::Schema.define { drop_table :test } } unless ex.metadata[:nodb]
26
+ end
27
+ end
28
+
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: database_sanitizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Marton Somogyi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pg
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.17'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord-comments
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: progress
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: iconv
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1'
111
+ description: Duplicate a databse with sanitization options using SQL comments
112
+ email:
113
+ - msomogyi@whitepages.com
114
+ executables:
115
+ - database_sanitizer
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - bin/database_sanitizer
125
+ - database_sanitizer.gemspec
126
+ - lib/database_sanitizer.rb
127
+ - lib/database_sanitizer/transformers.rb
128
+ - lib/database_sanitizer/version.rb
129
+ - spec/config/database.yml
130
+ - spec/database_exporter_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: https://github.com/mcbuddha/database_sanitizer
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.2.2
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Export your SQL database
156
+ test_files:
157
+ - spec/config/database.yml
158
+ - spec/database_exporter_spec.rb
159
+ - spec/spec_helper.rb