Skip to content

Commit

Permalink
Merge pull request #1 from SchemaPlus/multiple_schemas
Browse files Browse the repository at this point in the history
Implement schema plus multischema
  • Loading branch information
ronen committed Aug 28, 2015
2 parents 121762a + a93f50d commit 1205a4d
Show file tree
Hide file tree
Showing 16 changed files with 379 additions and 2 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/coverage
/tmp
/pkg
/Gemfile.local

*.lock
*.log
*.sqlite3
!gemfiles/**/*.sqlite3
.DS_Store
*/.DS_Store
16 changes: 16 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This file was auto-generated by the schema_dev tool, based on the data in
# ./schema_dev.yml
# Please do not edit this file; any changes will be overwritten next time
# schema_dev gets run.
---
sudo: false
rvm:
- 2.1.5
gemfile:
- gemfiles/activerecord-4.2/Gemfile.postgresql
env: POSTGRESQL_DB_USER=postgres
addons:
postgresql: '9.4'
before_script: bundle exec rake create_databases
after_script: bundle exec rake drop_databases
script: bundle exec rake travis
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "http://rubygems.org"

gemspec

File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local

22 changes: 22 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Copyright (c) 2015 Stenver Jerkku

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
125 changes: 123 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,123 @@
# schema_plus_multischema
Provides supports for using multiple schemas within a single database
[![Gem Version](https://badge.fury.io/rb/schema_plus_multischema.svg)](http://badge.fury.io/rb/schema_plus_multischema)
[![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_multischema.svg)](http://travis-ci.org/SchemaPlus/schema_plus_multischema)
[![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_multischema.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_multischema)
[![Dependency Status](https://gemnasium.com/lomba/schema_plus_multischema.svg)](https://gemnasium.com/SchemaPlus/schema_plus_multischema)

# SchemaPlusMultischema

Schema plus multischema is a schema plus extension for postgresql that adds support for multiple schemas for schema dumps.

SchemaPlusMultischema is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.

## Installation

<!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
<!-- These lines are auto-inserted from a schema_dev template -->
As usual:

```ruby
gem "schema_plus_multischema" # in a Gemfile
gem.add_dependency "schema_plus_multischema" # in a .gemspec
```

<!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->

## Compatibility

SchemaPlusMultischema is tested on:

<!-- SCHEMA_DEV: MATRIX - begin -->
<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
* ruby **2.1.5** with activerecord **4.2**, using **postgresql**

<!-- SCHEMA_DEV: MATRIX - end -->

## Usage

Using schema plus multiple schemas is easy - simply require it before you do a schema dump. If everything works, then the schema dump should include schema names before table names

For example, lets say we have a table ```wallets``` in schema ```private``` and table ```users``` in schema ```public```. Each user has 1 wallet. Without this gem, the schemadump would look like this:

```
create_table 'wallets' do
end
create_table 'users' do |t|
t.integer :wallet_id
end
```

With this gem, the schemadump will look like this:

```
create_table 'private.wallets' do
end
create_table 'public.users' do |t|
t.integer :wallet_id, null: false
end
```

The schema plus multischema also works with schema plus foreign keys. If schema plus foreign keys is enabled, the output will look like this:

```
create_table 'private.wallets' do
end
create_table 'public.users' do |t|
t.integer :wallet_id, null: false, foreign_key: {references: "private.wallets", name: "fk_public_users_wallet_id", on_update: :no_action, on_delete: :cascade}
end
```

## History

* 0.1.0 - Initial release

## Development & Testing

Are you interested in contributing to SchemaPlusMultischema? Thanks! Please follow
the standard protocol: fork, feature branch, develop, push, and issue pull
request.

Some things to know about to help you develop and test:

<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
<!-- These lines are auto-inserted from a schema_dev template -->
* **schema_dev**: SchemaPlus::Multischema uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
facilitate running rspec tests on the matrix of ruby, activerecord, and database
versions that the gem supports, both locally and on
[travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_multischema)

To to run rspec locally on the full matrix, do:

$ schema_dev bundle install
$ schema_dev rspec

You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.

The matrix of configurations is specified in `schema_dev.yml` in
the project root.


<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->

<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
<!-- These lines are auto-inserted from a schema_dev template -->
* **schema_plus_core**: SchemaPlus::Multischema uses the SchemaPlus::Core API that
provides middleware callback stacks to make it easy to extend
ActiveRecord's behavior. If that API is missing something you need for
your contribution, please head over to
[schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
an issue or pull request.

<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->

<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
<!-- These lines are auto-inserted from a schema_dev template -->
* **schema_monkey**: SchemaPlus::Multischema is implemented as a
[schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
convention-based protocols for extending ActiveRecord and using middleware stacks.

<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - end -->
9 changes: 9 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'bundler'
Bundler::GemHelper.install_tasks

require 'schema_dev/tasks'

task :default => :spec

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
4 changes: 4 additions & 0 deletions gemfiles/Gemfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'
gemspec :path => File.expand_path('..', __FILE__)

File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
3 changes: 3 additions & 0 deletions gemfiles/activerecord-4.2/Gemfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
eval File.read File.expand_path('../../Gemfile.base', __FILE__)

gem "activerecord", "~> 4.2.0"
10 changes: 10 additions & 0 deletions gemfiles/activerecord-4.2/Gemfile.postgresql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "pathname"
eval(Pathname.new(__FILE__).dirname.join("Gemfile.base").read, binding)

platform :ruby do
gem "pg"
end

platform :jruby do
gem 'activerecord-jdbcpostgresql-adapter'
end
11 changes: 11 additions & 0 deletions lib/schema_plus_multischema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'schema_plus/core'

require_relative 'schema_plus_multischema/version'
require_relative 'schema_plus_multischema/active_record/connection_adapters/postgresql_adapter'

module SchemaPlusMultischema
module ActiveRecord
end
end

SchemaMonkey.register SchemaPlusMultischema
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module SchemaPlusMultischema
module ActiveRecord
module ConnectionAdapters
module PostgresqlAdapter

# Returns the list of all tables in the schema search path or a specified schema.
def tables(name = nil)
select_tablenames_with_schemas <<-SQL
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname = ANY(current_schemas(false))
SQL
end

def select_tablenames_with_schemas(arel)
arel, binds = binds_from_relation arel, []
sql = to_sql(arel, binds)
execute_and_clear(sql, 'SCHEMA', binds) do |result|
if result.nfields > 0
rows = result.column_values(0).count
(0..(rows - 1)).map{ |i| "#{result.column_values(0)[i]}.#{result.column_values(1)[i]}" }
else
[]
end
end
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/schema_plus_multischema/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module SchemaPlusMultischema
VERSION = "0.1.0"
end
6 changes: 6 additions & 0 deletions schema_dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ruby:
- 2.1.5
activerecord:
- 4.2
db:
- postgresql
29 changes: 29 additions & 0 deletions schema_multiple_schemas.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'schema_plus_multischema/version'

Gem::Specification.new do |gem|
gem.name = "schema_plus_multischema"
gem.version = SchemaPlusMultischema::VERSION
gem.authors = ["Stenver Jerkku"]
gem.email = ["[email protected]"]
gem.summary = %q{Adds support for multiple schemas in activerecord when using Postgres}
gem.homepage = "https://github.com/SchemaPlus/schema_plus_multischema"
gem.license = "MIT"

gem.files = `git ls-files -z`.split("\x0")
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.require_paths = ["lib"]

gem.add_dependency "activerecord", "~> 4.2"
gem.add_dependency "schema_plus_core", "~> 0.5"

gem.add_development_dependency "bundler", "~> 1.7"
gem.add_development_dependency "rake", "~> 10.0"
gem.add_development_dependency "rspec", "~> 3.0"
gem.add_development_dependency "schema_dev", "~> 3.5", ">= 3.5.1"
gem.add_development_dependency "simplecov"
gem.add_development_dependency "simplecov-gem-profile"
end
72 changes: 72 additions & 0 deletions spec/schema_dumper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'spec_helper'

describe 'Schema dump' do
before(:each) do
ActiveRecord::Migration.suppress_messages do

ActiveRecord::Schema.define do
connection.schema_search_path='first,second'
connection.tables.each do |table| drop_table table, force: :cascade end

execute <<-SQL
CREATE SCHEMA IF NOT EXISTS first;
CREATE TABLE first.dogs
(
id INTEGER PRIMARY KEY
);
SQL

execute <<-SQL
CREATE SCHEMA IF NOT EXISTS second;
CREATE TABLE second.dogs
(
id INTEGER PRIMARY KEY
);
SQL

execute <<-SQL
CREATE SCHEMA IF NOT EXISTS second;
CREATE TABLE first.owners
(
id INTEGER PRIMARY KEY,
dog_id INTEGER NOT NULL
);
CREATE INDEX fk__first_owners_second_dogs ON first.owners USING btree (dog_id);
ALTER TABLE ONLY first.owners
ADD CONSTRAINT fk_first_owners_dog_id FOREIGN KEY (dog_id) REFERENCES second.dogs(id) ON DELETE CASCADE;
SQL

execute <<-SQL
CREATE SCHEMA IF NOT EXISTS second;
CREATE TABLE no_schema_prefix
(
id INTEGER PRIMARY KEY
);
SQL
end
end
end

def dump_schema(opts={})
stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore]) || []
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
stream.string
end

it 'should dump tables which are created without schema prefix' do
expect(dump_schema).to include('create_table "first.no_schema_prefix"')
end

it 'should dump tables with same names from different schemas' do
expect(dump_schema).to include('create_table "first.dogs"')
expect(dump_schema).to include('create_table "second.dogs"')
end

context 'when foreign key schema plus gem required' do
it 'should dump foreign key references with schema names' do
expect(dump_schema).to include('foreign_key: {references: "second.dogs", name: "fk_first_owners_dog_id"')
end
end
end
24 changes: 24 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'simplecov'
require 'simplecov-gem-profile'
require 'pry'
SimpleCov.start "gem"

$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))

require 'rspec'
require 'active_record'
require 'schema_plus_multischema'
require 'schema_dev/rspec'
require 'schema_plus_foreign_keys'

SchemaDev::Rspec.setup

Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}

RSpec.configure do |config|
config.warnings = true
end


SimpleCov.command_name "[ruby#{RUBY_VERSION}-activerecord#{::ActiveRecord.version}-#{ActiveRecord::Base.connection.adapter_name}]"

0 comments on commit 1205a4d

Please sign in to comment.