multitenancy_tools 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 607a5090d739ade79846b7d136b1b9b08fa28980
4
+ data.tar.gz: 8672d9af120642bcfc42f0b2431553210bd62ac7
5
+ SHA512:
6
+ metadata.gz: 142763f57d6f6f7b5356dc2d5160423ec312e54f59058036510d2267d741ec50431003733c49db5ac2af75be9d8c91c118a7e0bfe043b4c5ceb7070cadf06454
7
+ data.tar.gz: 8c699c5a0e5c89a793234c0fed79985ace9de9b67c465d40a176a04515a14a1df41ed36c3ee17937be7eb3c6426637fa6e349bc8ff878ddc7e23413de3eb7ae5
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /spec/database.yml
11
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.3
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in multitenancy_tools.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Locaweb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # MultitenancyTools
2
+
3
+ This gem is a collection of tools that can be used to handle multitenant
4
+ Ruby/Rails apps. The currently only supported database is PostgreSQL and there
5
+ is no plan to support other databases.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'multitenancy_tools'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install multitenancy_tools
22
+
23
+ ## Usage
24
+
25
+ #### Dumping the structure of a PostgreSQL schema to a SQL file
26
+
27
+ Please note that `pg_dump` must be on your `PATH`:
28
+
29
+ ```ruby
30
+ dumper = MultitenancyTools::SchemaDumper.new('database name', 'schema name')
31
+ dumper.dump_to('path/to/file.sql')
32
+ ```
33
+
34
+ #### Dumping the content of a table to a SQL file
35
+
36
+ Like `SchemaDumper`, this tool also requires `pg_dump` to be on the `PATH`:
37
+
38
+ ```ruby
39
+ dumper = MultitenancyTools::TableDumper.new('database name', 'schema name', 'table name')
40
+ dumper.dump_to('path/to/file.sql')
41
+ ```
42
+
43
+ #### Creating a new PostgreSQL schema using a SQL file as template
44
+
45
+ After using `SchemaDumper` to create the SQL template, you can use the following
46
+ class to create a new schema using this file as template:
47
+
48
+ ```ruby
49
+ creator = MultitenancyTools::SchemaCreator.new('schema name', ActiveRecord::Base.connection)
50
+ creator.create_from_file('path/to/file.sql')
51
+ ```
52
+
53
+ ## Development
54
+
55
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
56
+ edit `spec/database.yml` with your PostgreSQL database connection details (take
57
+ a look at the example in `spec/database.yml.example`). **IMPORTANT:** this
58
+ database will *be destroyed and recreated* on test execution.
59
+
60
+ You can use `rake spec` to run the tests. You can also run `bin/console` for an
61
+ interactive prompt that will allow you to experiment.
62
+
63
+ To install this gem onto your local machine, run `bundle exec rake install`.
64
+ To release a new version, update the version number in `version.rb`, and then
65
+ run `bundle exec rake release`, which will create a git tag for the version,
66
+ push git commits and tags, and push the `.gem` file to
67
+ [rubygems.org](https://rubygems.org).
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at
72
+ https://github.com/locaweb/multitenancy_tools.
73
+
74
+ ## License
75
+
76
+ The gem is available as open source under the terms of the
77
+ [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'multitenancy_tools'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,23 @@
1
+ module MultitenancyTools
2
+ # This class receives an SQL string and removes statements that should not
3
+ # be present on dumps generated by {SchemaDumper} and {TableDumper}.
4
+ class DumpCleaner
5
+ # @param [String] sql
6
+ def initialize(sql)
7
+ @sql = sql.dup
8
+ end
9
+
10
+ # Returns a new cleaned string.
11
+ #
12
+ # @return String
13
+ def clean
14
+ @sql.gsub!(/CREATE SCHEMA .*;\n/, '')
15
+ @sql.gsub!(/SET search_path .*;\n/, '')
16
+ @sql.gsub!(/SET statement_timeout .*;\n/, '')
17
+ @sql.gsub!(/SET lock_timeout .*;\n/, '')
18
+ @sql.gsub!(/^--(?:.*)\n+/, '')
19
+ @sql.gsub!(/\n+/, "\n")
20
+ @sql
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module MultitenancyTools
2
+ class PgDumpError < StandardError; end
3
+ end
@@ -0,0 +1,29 @@
1
+ module MultitenancyTools
2
+ # {SchemaCreator} can be used to create a schema on a PostgreSQL database
3
+ # using a SQL file as template. This template should be previously generated
4
+ # by {SchemaDumper}.
5
+ #
6
+ # @example
7
+ # creator = MultitenancyTools::SchemaCreator.new('schema name', ActiveRecord::Base.connection)
8
+ # creator.create_from_file('path/to/file.sql')
9
+ class SchemaCreator
10
+ # @param schema [String] schema name
11
+ # @param connection [ActiveRecord::ConnectionAdapters::PostgreSQLAdapter] connection adapter
12
+ def initialize(schema, connection)
13
+ @schema = schema
14
+ @connection = connection
15
+ end
16
+
17
+ # Creates the schema using a SQL file that was generated by {SchemaDumper}.
18
+ #
19
+ # @param file [String] path to a SQL file
20
+ def create_from_file(file)
21
+ quoted_schema_name = @connection.quote_table_name(@schema)
22
+
23
+ SchemaSwitcher.new(@schema, @connection).run do
24
+ @connection.create_schema(quoted_schema_name)
25
+ @connection.execute(File.read(file))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ require 'open3'
2
+
3
+ module MultitenancyTools
4
+ # {SchemaDumper} can be used to generate SQL dumps of the structure of a
5
+ # PostgreSQL schema. It requires pg_dump.
6
+ #
7
+ # The generated dump DOES NOT contain:
8
+ # * privilege statements (GRANT/REVOKE)
9
+ # * tablespace assigments
10
+ # * ownership information
11
+ # * any table data
12
+ #
13
+ # {SchemaDumper} is suitable to create SQL templates for {SchemaCreator}.
14
+ #
15
+ # @see http://www.postgresql.org/docs/9.3/static/app-pgdump.html
16
+ # pg_dump
17
+ # @example
18
+ # dumper = MultitenancyTools::SchemaDumper.new('my_db', 'my_schema')
19
+ # dumper.dump_to('path/to/file.sql')
20
+ class SchemaDumper
21
+ # @param database [String] database name
22
+ # @param schema [String] schema name
23
+ def initialize(database, schema)
24
+ @database = database
25
+ @schema = schema
26
+ end
27
+
28
+ # Generates a dump an writes it into a file. Please see {IO.new} for open
29
+ # modes.
30
+ #
31
+ # @see http://ruby-doc.org/core-2.2.2/IO.html#method-c-new-label-Open+Mode
32
+ # IO Open Modes
33
+ # @param file [String] file path
34
+ # @param mode [String] IO open mode
35
+ def dump_to(file, mode: 'w')
36
+ stdout, stderr, status = Open3.capture3(
37
+ 'pg_dump',
38
+ '--schema', @schema,
39
+ '--schema-only',
40
+ '--no-privileges',
41
+ '--no-tablespaces',
42
+ '--no-owner',
43
+ '--dbname', @database
44
+ )
45
+
46
+ fail(PgDumpError, stderr) unless status.success?
47
+
48
+ File.open(file, mode) do |f|
49
+ f.write DumpCleaner.new(stdout).clean
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ module MultitenancyTools
2
+ # {SchemaSwitcher} can be used to switch between PostgreSQL schemas on a
3
+ # connection. It uses PostgreSQL search_path to achieve this functionality.
4
+ class SchemaSwitcher
5
+ # @param schema [String] schema name
6
+ # @param connection [ActiveRecord::ConnectionAdapters::PostgreSQLAdapter] connection adapter
7
+ def initialize(schema, connection)
8
+ @connection = connection
9
+ @schema = @connection.quote(schema)
10
+ end
11
+
12
+ # This sets the connection search_path to use only the current schema,
13
+ # yields the block and then change search_path back to its previous value.
14
+ def run(&block)
15
+ original_path = @connection.schema_search_path
16
+ @connection.schema_search_path = @schema
17
+ yield
18
+ ensure
19
+ @connection.schema_search_path = original_path
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ require 'open3'
2
+
3
+ module MultitenancyTools
4
+ # {TableDumper} can be used to generate SQL dumps of the structure and,
5
+ # unlike {SchemaDumper}, the data of a PostgreSQL table. It requires pg_dump.
6
+ #
7
+ # The generated dump DOES NOT contain:
8
+ # * privilege statements (GRANT/REVOKE)
9
+ # * tablespace assigments
10
+ # * ownership information
11
+ #
12
+ # The dump will use INSERTs instead of COPY statements.
13
+ #
14
+ # @see http://www.postgresql.org/docs/9.3/static/app-pgdump.html
15
+ # pg_dump
16
+ # @example
17
+ # dumper = MultitenancyTools::TableDumper.new('db name', 'schema name', 'table name')
18
+ # dumper.dump_to('path/to/file.sql')
19
+ class TableDumper
20
+ # @param database [String] database name
21
+ # @param schema [String] schema name
22
+ # @param table [String] table name
23
+ def initialize(database, schema, table)
24
+ @database = database
25
+ @schema = schema
26
+ @table = table
27
+ end
28
+
29
+ # Generates a dump an writes it into a file. Please see {IO.new} for open
30
+ # modes.
31
+ #
32
+ # @see http://ruby-doc.org/core-2.2.2/IO.html#method-c-new-label-Open+Mode
33
+ # IO Open Modes
34
+ # @param file [String] file path
35
+ # @param mode [String] IO open mode
36
+ def dump_to(file, mode: 'w')
37
+ stdout, stderr, status = Open3.capture3(
38
+ 'pg_dump',
39
+ '--table', "#{@schema}.#{@table}",
40
+ '--data-only',
41
+ '--no-privileges',
42
+ '--no-tablespaces',
43
+ '--no-owner',
44
+ '--inserts',
45
+ '--dbname', @database
46
+ )
47
+
48
+ fail(PgDumpError, stderr) unless status.success?
49
+
50
+ File.open(file, mode) do |f|
51
+ f.write DumpCleaner.new(stdout).clean
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module MultitenancyTools
2
+ VERSION = '0.1.7'
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'multitenancy_tools/version'
2
+ require 'multitenancy_tools/errors'
3
+ require 'multitenancy_tools/dump_cleaner'
4
+ require 'multitenancy_tools/schema_dumper'
5
+ require 'multitenancy_tools/schema_creator'
6
+ require 'multitenancy_tools/table_dumper'
7
+ require 'multitenancy_tools/schema_switcher'
8
+
9
+ module MultitenancyTools
10
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multitenancy_tools/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'multitenancy_tools'
8
+ spec.version = MultitenancyTools::VERSION
9
+ spec.authors = ['Lenon Marcel', 'Rafael Timbó', 'Lucas Nogueira',
10
+ 'Rodolfo Liviero']
11
+ spec.email = ['lenon.marcel@gmail.com', 'rafaeltimbosoares@gmail.com',
12
+ 'lukspn.27@gmail.com', 'rodolfoliviero@gmail.com']
13
+ spec.summary = 'A collection of tools for multitenant Ruby/Rails apps'
14
+ spec.description = 'A collection of tools for multitenant Ruby/Rails apps'
15
+ spec.homepage = 'https://github.com/locaweb/multitenancy_tools'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.10'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.3.0'
26
+ spec.add_development_dependency 'activerecord', '~> 4.2.0'
27
+ spec.add_development_dependency 'pg'
28
+ spec.add_development_dependency 'yard'
29
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multitenancy_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ platform: ruby
6
+ authors:
7
+ - Lenon Marcel
8
+ - Rafael Timbó
9
+ - Lucas Nogueira
10
+ - Rodolfo Liviero
11
+ autorequire:
12
+ bindir: exe
13
+ cert_chain: []
14
+ date: 2015-07-20 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bundler
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '1.10'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.10'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '10.0'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '10.0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: rspec
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: 3.3.0
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: 3.3.0
58
+ - !ruby/object:Gem::Dependency
59
+ name: activerecord
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: 4.2.0
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: 4.2.0
72
+ - !ruby/object:Gem::Dependency
73
+ name: pg
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: yard
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ description: A collection of tools for multitenant Ruby/Rails apps
101
+ email:
102
+ - lenon.marcel@gmail.com
103
+ - rafaeltimbosoares@gmail.com
104
+ - lukspn.27@gmail.com
105
+ - rodolfoliviero@gmail.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".gitignore"
111
+ - ".rspec"
112
+ - ".travis.yml"
113
+ - Gemfile
114
+ - LICENSE.txt
115
+ - README.md
116
+ - Rakefile
117
+ - bin/console
118
+ - bin/setup
119
+ - lib/multitenancy_tools.rb
120
+ - lib/multitenancy_tools/dump_cleaner.rb
121
+ - lib/multitenancy_tools/errors.rb
122
+ - lib/multitenancy_tools/schema_creator.rb
123
+ - lib/multitenancy_tools/schema_dumper.rb
124
+ - lib/multitenancy_tools/schema_switcher.rb
125
+ - lib/multitenancy_tools/table_dumper.rb
126
+ - lib/multitenancy_tools/version.rb
127
+ - multitenancy_tools.gemspec
128
+ homepage: https://github.com/locaweb/multitenancy_tools
129
+ licenses:
130
+ - MIT
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubyforge_project:
148
+ rubygems_version: 2.4.6
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: A collection of tools for multitenant Ruby/Rails apps
152
+ test_files: []
153
+ has_rdoc: