Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

now support a different default schema_search_path than public

  • Loading branch information...
commit 505ea1f11b6560912327728f8f973e3f686a4e11 1 parent 2c15e0a
@bradrobertson bradrobertson authored
View
3  .pryrc
@@ -0,0 +1,3 @@
+if defined?(Rails) && Rails.env
+ extend Rails::ConsoleMethods
+end
View
23 README.md
@@ -85,20 +85,19 @@ To set config options, add this to your initializer:
### Excluding models
-If you have some models that should always access the 'root' database, you can specify this by configuring
-Apartment using `Apartment.configure`. This will yield a config object for you. You can set excluded models like so:
+If you have some models that should always access the 'root' database, you can specify this by configuring Apartment using `Apartment.configure`. This will yield a config object for you. You can set excluded models like so:
config.excluded_models = ["User", "Company"] # these models will not be multi-tenanted, but remain in the global (public) namespace
Note that a string representation of the model name is now the standard so that models are properly constantized when reloaded in development
-### Handling Environments
+### Providing a default schema
-By default, when not using postgresql schemas, Apartment will prepend the environment to the database name
-to ensure there is no conflict between your environments. This is mainly for the benefit of your development
-and test environments. If you wish to turn this option off in production, you could do something like:
+By default, ActiveRecord will use `"$user", public` as the default `schema_search_path`. This can be modified if you wish to use a different default schema be setting:
- config.prepend_environment = !Rails.env.production?
+ config.default_schema = "some_other_schema"
+
+With that set, all excluded models will use this schema as the table name prefix instead of `public` and `reset` on `Apartment::Database` will return to this schema also
### Managing Migrations
@@ -119,7 +118,15 @@ You can then migration your databases using the rake task:
This basically invokes `Apartment::Database.migrate(#{db_name})` for each database name supplied
from `Apartment.database_names`
-### Delayed::Job
+### Handling Environments
+
+By default, when not using postgresql schemas, Apartment will prepend the environment to the database name
+to ensure there is no conflict between your environments. This is mainly for the benefit of your development
+and test environments. If you wish to turn this option off in production, you could do something like:
+
+ config.prepend_environment = !Rails.env.production?
+
+## Delayed::Job
If using Rails ~> 3.2, you *must* use `delayed_job ~> 3.0`. It has better Rails 3 support plus has some major changes that affect the serialization of models.
I haven't been able to get `psych` working whatsoever as the YAML parser, so to get things to work properly, you must explicitly set the parser to `syck` *before* requiring `delayed_job`
View
5 lib/apartment.rb
@@ -4,7 +4,7 @@ module Apartment
class << self
attr_accessor :use_postgres_schemas, :seed_after_create, :prepend_environment
- attr_writer :database_names, :excluded_models
+ attr_writer :database_names, :excluded_models, :default_schema
# configure apartment with available options
def configure
@@ -21,6 +21,9 @@ def excluded_models
@excluded_models || []
end
+ def default_schema
+ @default_schema || "public"
+ end
end
autoload :Database, 'apartment/database'
View
10 lib/apartment/adapters/postgresql_adapter.rb
@@ -4,7 +4,7 @@ module Database
def self.postgresql_adapter(config)
Apartment.use_postgres_schemas ?
- Adapters::PostgresqlSchemaAdapter.new(config, :schema_search_path => ActiveRecord::Base.connection.schema_search_path) :
+ Adapters::PostgresqlSchemaAdapter.new(config) :
Adapters::PostgresqlAdapter.new(config)
end
end
@@ -53,7 +53,7 @@ def drop(database)
end
# Reset search path to default search_path
- # Set the table_name to always use the public namespace for excluded models
+ # Set the table_name to always use the default namespace for excluded models
#
def process_excluded_models
Apartment.excluded_models.each do |excluded_model|
@@ -66,14 +66,14 @@ def process_excluded_models
excluded_model.constantize.tap do |klass|
# some models (such as delayed_job) seem to load and cache their column names before this,
- # so would never get the public prefix, so reset first
+ # so would never get the default prefix, so reset first
klass.reset_column_information
# Ensure that if a schema *was* set, we override
table_name = klass.table_name.split('.', 2).last
# Not sure why, but Delayed::Job somehow ignores table_name_prefix... so we'll just manually set table name instead
- klass.table_name = "public.#{table_name}"
+ klass.table_name = "#{Apartment.default_schema}.#{table_name}"
end
end
end
@@ -83,7 +83,7 @@ def process_excluded_models
# @return {String} default schema search path
#
def reset
- ActiveRecord::Base.connection.schema_search_path = @defaults[:schema_search_path]
+ ActiveRecord::Base.connection.schema_search_path = Apartment.default_schema
end
protected
View
1  lib/apartment/database.rb
@@ -3,6 +3,7 @@
module Apartment
# The main entry point to Apartment functions
+ #
module Database
extend self
View
1  spec/config/database.yml
@@ -4,6 +4,7 @@ connections:
database: apartment_postgresql_test
min_messages: WARNING
username: postgres
+ schema_search_path: public
password:
mysql:
View
48 spec/database_spec.rb
@@ -26,42 +26,42 @@
end
context "using postgresql" do
-
+
# See apartment.yml file in dummy app config
-
+
let(:config){ Apartment::Test.config['connections']['postgresql'].symbolize_keys }
let(:database){ Apartment::Test.next_db }
let(:database2){ Apartment::Test.next_db }
-
+
before do
Apartment.use_postgres_schemas = true
ActiveRecord::Base.establish_connection config
Apartment::Test.load_schema # load the Rails schema in the public db schema
subject.stub(:config).and_return config # Use postgresql database config for this test
end
-
+
describe "#adapter" do
before do
subject.reload!
end
-
+
it "should load postgresql adapter" do
subject.adapter
Apartment::Adapters::PostgresqlAdapter.should be_a(Class)
end
-
+
it "should raise exception with invalid adapter specified" do
subject.stub(:config).and_return config.merge(:adapter => 'unkown')
-
+
expect {
Apartment::Database.adapter
}.to raise_error
end
-
+
end
-
+
context "with schemas" do
-
+
before do
Apartment.configure do |config|
config.excluded_models = []
@@ -70,25 +70,25 @@
end
subject.create database
end
-
+
after{ subject.drop database }
-
+
describe "#create" do
it "should seed data" do
subject.switch database
User.count.should be > 0
end
end
-
+
describe "#switch" do
-
+
let(:x){ rand(3) }
-
+
context "creating models" do
-
+
before{ subject.create database2 }
after{ subject.drop database2 }
-
+
it "should create a model instance in the current schema" do
subject.switch database2
db2_count = User.count + x.times{ User.create }
@@ -103,20 +103,20 @@
User.count.should == db_count
end
end
-
+
context "with excluded models" do
-
+
before do
Apartment.configure do |config|
config.excluded_models = ["Company"]
end
subject.init
end
-
+
it "should create excluded models in public schema" do
subject.reset # ensure we're on public schema
count = Company.count + x.times{ Company.create }
-
+
subject.switch database
x.times{ Company.create }
Company.count.should == count + x
@@ -124,10 +124,10 @@
Company.count.should == count + x
end
end
-
+
end
-
+
end
-
+
end
end
View
39 spec/examples/schema_adapter_examples.rb
@@ -9,15 +9,26 @@
describe "#init" do
- it "should process model exclusions" do
+ before do
Apartment.configure do |config|
config.excluded_models = ["Company"]
end
+ end
+ it "should process model exclusions" do
Apartment::Database.init
Company.table_name.should == "public.companies"
end
+
+ context "with a default_schema", :default_schema => true do
+
+ it "should set the proper table_name on excluded_models" do
+ Apartment::Database.init
+
+ Company.table_name.should == "#{default_schema}.companies"
+ end
+ end
end
#
@@ -91,7 +102,7 @@
it "should reset" do
subject.process(schema1)
- connection.schema_search_path.should == public_schema
+ connection.schema_search_path.should start_with public_schema
end
end
@@ -99,7 +110,15 @@
it "should reset connection" do
subject.switch(schema1)
subject.reset
- connection.schema_search_path.should == public_schema
+ connection.schema_search_path.should start_with public_schema
+ end
+
+ context "with default_schema", :default_schema => true do
+ it "should reset to the default schema" do
+ subject.switch(schema1)
+ subject.reset
+ connection.schema_search_path.should start_with default_schema
+ end
end
end
@@ -134,6 +153,20 @@
after{ subject.drop(db) }
end
+
+ describe "with default_schema specified", :default_schema => true do
+ before do
+ subject.switch(schema1)
+ end
+
+ it "should switch out the default schema rather than public" do
+ connection.schema_search_path.should_not include default_schema
+ end
+
+ it "should still switch to the switched schema" do
+ connection.schema_search_path.should start_with schema1
+ end
+ end
end
describe "#current_database" do
View
21 spec/support/apartment_helpers.rb
@@ -1,38 +1,41 @@
module Apartment
module Test
-
+
extend self
-
+
def reset
Apartment.excluded_models = nil
Apartment.use_postgres_schemas = nil
Apartment.seed_after_create = nil
+ Apartment.default_schema = nil
end
-
+
def next_db
@x ||= 0
"db_#{@x += 1}"
end
-
+
def drop_schema(schema)
ActiveRecord::Base.connection.execute("DROP SCHEMA IF EXISTS #{schema} CASCADE") rescue true
end
-
+
+ # Use this if you don't want to import schema.rb etc... but need the postgres schema to exist
+ # basically for speed purposes
def create_schema(schema)
ActiveRecord::Base.connection.execute("CREATE SCHEMA #{schema}")
end
-
+
def load_schema
silence_stream(STDOUT){ load(Rails.root.join('db', 'schema.rb')) }
end
-
+
def migrate
ActiveRecord::Migrator.migrate(Rails.root + ActiveRecord::Migrator.migrations_path)
end
-
+
def rollback
ActiveRecord::Migrator.rollback(Rails.root + ActiveRecord::Migrator.migrations_path)
end
-
+
end
end
View
16 spec/support/contexts.rb
@@ -0,0 +1,16 @@
+# Some shared contexts for specs
+
+shared_context "with default schema", :default_schema => true do
+ let(:default_schema){ Apartment::Test.next_db }
+
+ before do
+ Apartment::Test.create_schema(default_schema)
+ Apartment.default_schema = default_schema
+ end
+
+ after do
+ # resetting default_schema so we can drop and any further resets won't try to access droppped schema
+ Apartment.default_schema = nil
+ Apartment::Test.drop_schema(default_schema)
+ end
+end
View
8 spec/support/requirements.rb
@@ -7,9 +7,9 @@ module Spec
#
#
module AdapterRequirements
-
+
extend ActiveSupport::Concern
-
+
included do
let(:db1){ Apartment::Test.next_db }
let(:db2){ Apartment::Test.next_db }
@@ -28,7 +28,7 @@ module AdapterRequirements
# sometimes we manually drop these schemas in testing, don't care if we can't drop, hence rescue
subject.drop(db1) rescue true
subject.drop(db2) rescue true
-
+
ActiveRecord::Base.clear_all_connections!
Apartment::Database.reload!
end
@@ -39,7 +39,7 @@ module AdapterRequirements
raise "You must define a `#{method}` method in your host group"
end unless defined?(method)
end
-
+
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.