apartment 0.22.1 → 0.23.0

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.rspec +2 -1
  4. data/.travis.yml +3 -1
  5. data/Appraisals +7 -0
  6. data/Gemfile +0 -21
  7. data/HISTORY.md +6 -0
  8. data/README.md +13 -71
  9. data/Rakefile +4 -2
  10. data/TODO.md +0 -5
  11. data/apartment.gemspec +19 -0
  12. data/gemfiles/rails3.2.gemfile +7 -0
  13. data/gemfiles/rails4.0.gemfile +7 -0
  14. data/lib/apartment.rb +2 -28
  15. data/lib/apartment/adapters/abstract_adapter.rb +0 -2
  16. data/lib/apartment/adapters/abstract_jdbc_adapter.rb +2 -0
  17. data/lib/apartment/adapters/jdbc_mysql_adapter.rb +2 -0
  18. data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +1 -1
  19. data/lib/apartment/adapters/mysql2_adapter.rb +2 -3
  20. data/lib/apartment/adapters/postgis_adapter.rb +0 -1
  21. data/lib/apartment/adapters/postgresql_adapter.rb +2 -3
  22. data/lib/apartment/adapters/sqlite3_adapter.rb +2 -0
  23. data/lib/apartment/database.rb +0 -4
  24. data/lib/apartment/elevators/domain.rb +2 -0
  25. data/lib/apartment/elevators/first_subdomain.rb +2 -0
  26. data/lib/apartment/elevators/generic.rb +3 -0
  27. data/lib/apartment/elevators/host_hash.rb +2 -0
  28. data/lib/apartment/elevators/subdomain.rb +19 -2
  29. data/lib/apartment/migrator.rb +2 -1
  30. data/lib/apartment/railtie.rb +2 -2
  31. data/lib/apartment/reloader.rb +0 -3
  32. data/lib/apartment/version.rb +2 -2
  33. data/lib/tasks/apartment.rake +2 -0
  34. data/spec/adapters/jdbc_mysql_adapter_spec.rb +1 -3
  35. data/spec/adapters/jdbc_postgresql_adapter_spec.rb +1 -3
  36. data/spec/adapters/mysql2_adapter_spec.rb +1 -2
  37. data/spec/adapters/postgresql_adapter_spec.rb +1 -2
  38. data/spec/adapters/sqlite3_adapter_spec.rb +1 -2
  39. data/spec/database_spec.rb +32 -50
  40. data/spec/dummy/app/models/user.rb +0 -2
  41. data/spec/dummy/config/application.rb +2 -0
  42. data/spec/dummy/config/environments/development.rb +2 -0
  43. data/spec/dummy/config/environments/production.rb +2 -0
  44. data/spec/dummy/config/environments/test.rb +1 -2
  45. data/spec/dummy/config/initializers/apartment.rb +1 -1
  46. data/spec/dummy/db/seeds.rb +1 -4
  47. data/spec/examples/elevator_examples.rb +4 -4
  48. data/spec/integration/apartment_rake_integration_spec.rb +15 -19
  49. data/spec/integration/middleware/domain_elevator_spec.rb +4 -3
  50. data/spec/integration/middleware/generic_elevator_spec.rb +4 -3
  51. data/spec/integration/middleware/subdomain_elevator_spec.rb +29 -3
  52. data/spec/integration/query_caching_spec.rb +8 -4
  53. data/spec/schemas/v1.rb +16 -0
  54. data/spec/schemas/v2.rb +43 -0
  55. data/spec/schemas/v3.rb +49 -0
  56. data/spec/spec_helper.rb +5 -11
  57. data/spec/support/apartment_helpers.rb +4 -2
  58. data/spec/support/contexts.rb +15 -19
  59. data/spec/support/requirements.rb +1 -17
  60. data/spec/support/setup.rb +47 -0
  61. data/spec/tasks/apartment_rake_spec.rb +6 -3
  62. data/spec/unit/config_spec.rb +3 -3
  63. data/spec/unit/middleware/domain_elevator_spec.rb +1 -2
  64. data/spec/{integration → unit}/middleware/first_subdomain_elevator_spec.rb +1 -0
  65. data/spec/unit/middleware/host_hash_elevator_spec.rb +1 -2
  66. data/spec/unit/middleware/subdomain_elevator_spec.rb +1 -2
  67. data/spec/unit/migrator_spec.rb +5 -4
  68. data/spec/unit/reloader_spec.rb +6 -4
  69. metadata +130 -14
  70. data/lib/apartment/delayed_job/enqueue.rb +0 -26
  71. data/lib/apartment/delayed_job/hooks.rb +0 -26
  72. data/lib/apartment/delayed_job/psych_ext.rb +0 -61
  73. data/lib/apartment/delayed_job/requirements.rb +0 -23
  74. data/lib/apartment/delayed_job/syck_ext.rb +0 -29
  75. data/spec/dummy/lib/fake_dj_class.rb +0 -6
  76. data/spec/integration/delayed_job_integration_spec.rb +0 -99
@@ -1,34 +1,34 @@
1
1
  require 'spec_helper'
2
2
  require 'rake'
3
3
 
4
- describe "apartment rake tasks" do
4
+ describe "apartment rake tasks", database: :postgresql do
5
5
 
6
6
  before do
7
7
  @rake = Rake::Application.new
8
8
  Rake.application = @rake
9
9
  Dummy::Application.load_tasks
10
10
 
11
- # somehow this misc.rake file gets lost in the shuffle
12
- # it defines a `rails_env` task that our db:migrate depends on
13
- # No idea why, but during the tests, we somehow lose this tasks, so we get an error when testing migrations
14
- # This is STUPID!
15
- load "rails/tasks/misc.rake"
16
- end
17
-
18
- after do
19
- Rake.application = nil
20
- end
11
+ # rails tasks running F up the schema...
12
+ Rake::Task.define_task('db:migrate')
13
+ Rake::Task.define_task('db:seed')
14
+ Rake::Task.define_task('db:rollback')
15
+ Rake::Task.define_task('db:migrate:up')
16
+ Rake::Task.define_task('db:migrate:down')
17
+ Rake::Task.define_task('db:migrate:redo')
21
18
 
22
- before do
23
19
  Apartment.configure do |config|
20
+ config.use_schemas = true
24
21
  config.excluded_models = ["Company"]
25
- config.database_names = lambda{ Company.scoped.collect(&:database) }
22
+ config.database_names = lambda{ Company.pluck(:database) }
26
23
  end
24
+ Apartment::Database.reload!(config)
27
25
 
28
26
  # fix up table name of shared/excluded models
29
27
  Company.table_name = 'public.companies'
30
28
  end
31
29
 
30
+ after { Rake.application = nil }
31
+
32
32
  context "with x number of databases" do
33
33
 
34
34
  let(:x){ 1 + rand(5) } # random number of dbs to create
@@ -49,7 +49,7 @@ describe "apartment rake tasks" do
49
49
 
50
50
  describe "#migrate" do
51
51
  it "should migrate all databases" do
52
- Apartment::Migrator.should_receive(:migrate).exactly(company_count).times
52
+ ActiveRecord::Migrator.should_receive(:migrate).exactly(company_count+1).times
53
53
 
54
54
  @rake['apartment:migrate'].invoke
55
55
  end
@@ -57,12 +57,9 @@ describe "apartment rake tasks" do
57
57
 
58
58
  describe "#rollback" do
59
59
  it "should rollback all dbs" do
60
- db_names.each do |name|
61
- Apartment::Migrator.should_receive(:rollback).with(name, anything)
62
- end
60
+ ActiveRecord::Migrator.should_receive(:rollback).exactly(company_count+1).times
63
61
 
64
62
  @rake['apartment:rollback'].invoke
65
- @rake['apartment:migrate'].invoke # migrate again so that our next test 'seed' can run (requires migrations to be complete)
66
63
  end
67
64
  end
68
65
 
@@ -73,6 +70,5 @@ describe "apartment rake tasks" do
73
70
  @rake['apartment:seed'].invoke
74
71
  end
75
72
  end
76
-
77
73
  end
78
74
  end
@@ -1,9 +1,10 @@
1
1
  require 'spec_helper'
2
+ require 'apartment/elevators/domain'
2
3
 
3
- describe Apartment::Elevators::Domain, :elevator => true do
4
+ describe Apartment::Elevators::Domain, elevator: true do
4
5
 
5
- let(:domain1) { "http://#{database1}.com" }
6
- let(:domain2) { "http://#{database2}.com" }
6
+ let(:domain1) { "http://#{db1}.com" }
7
+ let(:domain2) { "http://#{db2}.com" }
7
8
 
8
9
  it_should_behave_like "an apartment elevator"
9
10
  end
@@ -1,10 +1,11 @@
1
1
  require 'spec_helper'
2
+ require 'apartment/elevators/generic'
2
3
 
3
- describe Apartment::Elevators::Generic, :elevator => true do
4
+ describe Apartment::Elevators::Generic, elevator: true do
4
5
 
5
6
  # NOTE, see spec/dummy/config/application.rb to see the Proc that defines the behaviour here
6
- let(:domain1) { "http://#{database1}.com?db=#{database1}" }
7
- let(:domain2) { "http://#{database2}.com?db=#{database2}" }
7
+ let(:domain1) { "http://#{db1}.com?db=#{db1}" }
8
+ let(:domain2) { "http://#{db2}.com?db=#{db2}" }
8
9
 
9
10
  it_should_behave_like "an apartment elevator"
10
11
  end
@@ -1,9 +1,35 @@
1
1
  require 'spec_helper'
2
+ require 'apartment/elevators/generic'
2
3
 
3
- describe Apartment::Elevators::Subdomain, :elevator => true do
4
+ describe Apartment::Elevators::Subdomain, elevator: true do
4
5
 
5
- let(:domain1) { "http://#{database1}.example.com" }
6
- let(:domain2) { "http://#{database2}.example.com" }
6
+ let(:domain1) { "http://#{db1}.example.com" }
7
+ let(:domain2) { "http://#{db2}.example.com" }
7
8
 
8
9
  it_should_behave_like "an apartment elevator"
10
+
11
+ context "With Subdomain Excluded" do
12
+ let(:domain_with_excluded_subdomain) { "http://www.example.com" }
13
+
14
+ before do
15
+ Apartment::Elevators::Subdomain.excluded_subdomains = %w(www)
16
+ # FIXME:
17
+ # This is used because the dummy app includes all three middlewares. The domain middleware specifically
18
+ # tries to lookup the example schema and tries to switch to it. I don't know how to go around this.
19
+ Apartment::Database.create("example")
20
+ end
21
+
22
+ it_should_behave_like "an apartment elevator"
23
+
24
+ it "shouldnt switch the schema if the subdomain is excluded" do
25
+ ActiveRecord::Base.connection.schema_search_path.scan(/\w+/).should_not include("www")
26
+ visit(domain_with_excluded_subdomain)
27
+ ActiveRecord::Base.connection.schema_search_path.scan(/\w+/).should_not include("www")
28
+ end
29
+
30
+ after do
31
+ Apartment::Elevators::Subdomain.excluded_subdomains = []
32
+ Apartment::Database.drop("example")
33
+ end
34
+ end
9
35
  end
@@ -1,25 +1,29 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'query caching' do
4
+ let(:db_names) { [db1, db2] }
5
+
4
6
  before do
5
7
  Apartment.configure do |config|
6
8
  config.excluded_models = ["Company"]
7
- config.database_names = lambda{ Company.scoped.collect(&:database) }
9
+ config.database_names = lambda{ Company.pluck(:database) }
10
+ config.use_schemas = true
8
11
  end
9
12
 
13
+ Apartment::Database.reload!(config)
14
+
10
15
  db_names.each do |db_name|
11
16
  Apartment::Database.create(db_name)
12
- Company.create :database => db_name
17
+ Company.create database: db_name
13
18
  end
14
19
  end
15
20
 
16
21
  after do
17
22
  db_names.each{ |db| Apartment::Database.drop(db) }
23
+ Apartment::Database.reset
18
24
  Company.delete_all
19
25
  end
20
26
 
21
- let(:db_names) { 2.times.map{ Apartment::Test.next_db } }
22
-
23
27
  it 'clears the ActiveRecord::QueryCache after switching databases' do
24
28
  db_names.each do |db_name|
25
29
  Apartment::Database.switch db_name
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 0) do
15
+
16
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 20110613152810) do
15
+
16
+ create_table "companies", :force => true do |t|
17
+ t.boolean "dummy"
18
+ t.string "database"
19
+ end
20
+
21
+ create_table "delayed_jobs", :force => true do |t|
22
+ t.integer "priority", :default => 0
23
+ t.integer "attempts", :default => 0
24
+ t.text "handler"
25
+ t.text "last_error"
26
+ t.datetime "run_at"
27
+ t.datetime "locked_at"
28
+ t.datetime "failed_at"
29
+ t.string "locked_by"
30
+ t.datetime "created_at"
31
+ t.datetime "updated_at"
32
+ t.string "queue"
33
+ end
34
+
35
+ add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
36
+
37
+ create_table "users", :force => true do |t|
38
+ t.string "name"
39
+ t.datetime "birthdate"
40
+ t.string "sex"
41
+ end
42
+
43
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 20111202022214) do
15
+
16
+ create_table "books", :force => true do |t|
17
+ t.string "name"
18
+ t.integer "pages"
19
+ t.datetime "published"
20
+ end
21
+
22
+ create_table "companies", :force => true do |t|
23
+ t.boolean "dummy"
24
+ t.string "database"
25
+ end
26
+
27
+ create_table "delayed_jobs", :force => true do |t|
28
+ t.integer "priority", :default => 0
29
+ t.integer "attempts", :default => 0
30
+ t.text "handler"
31
+ t.text "last_error"
32
+ t.datetime "run_at"
33
+ t.datetime "locked_at"
34
+ t.datetime "failed_at"
35
+ t.string "locked_by"
36
+ t.datetime "created_at"
37
+ t.datetime "updated_at"
38
+ t.string "queue"
39
+ end
40
+
41
+ add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
42
+
43
+ create_table "users", :force => true do |t|
44
+ t.string "name"
45
+ t.datetime "birthdate"
46
+ t.string "sex"
47
+ end
48
+
49
+ end
data/spec/spec_helper.rb CHANGED
@@ -23,21 +23,15 @@ Rails.backtrace_cleaner.remove_silencers!
23
23
  # Load support files
24
24
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
25
25
 
26
-
27
26
  RSpec.configure do |config|
28
27
 
29
- config.include RSpec::Integration::CapybaraSessions, :type => :request
30
-
31
- config.before(:all) do
32
- # Ensure that each test starts with a clean connection
33
- # Necessary as some tests will leak things like current_schema into the next test
34
- ActiveRecord::Base.clear_all_connections!
35
- end
28
+ config.include RSpec::Integration::CapybaraSessions, type: :request
29
+ config.include Apartment::Spec::Setup
36
30
 
37
- config.after(:each) do
38
- Apartment.reset
31
+ # Somewhat brutal hack so that rails 4 postgres extensions don't modify this file
32
+ config.after(:suite) do
33
+ `git checkout -- spec/dummy/db/schema.rb`
39
34
  end
40
-
41
35
  end
42
36
 
43
37
  # Load shared examples, must happen after configure for RSpec 3
@@ -25,8 +25,10 @@ module Apartment
25
25
  ActiveRecord::Base.connection.execute("CREATE SCHEMA #{schema}")
26
26
  end
27
27
 
28
- def load_schema
29
- silence_stream(STDOUT){ load(Rails.root.join('db', 'schema.rb')) }
28
+ def load_schema(version = 3)
29
+ file = File.expand_path("../../schemas/v#{version}.rb", __FILE__)
30
+
31
+ silence_stream(STDOUT){ load(file) }
30
32
  end
31
33
 
32
34
  def migrate
@@ -16,28 +16,24 @@ shared_context "with default schema", :default_schema => true do
16
16
  end
17
17
 
18
18
  # Some default setup for elevator specs
19
- shared_context "elevators", :elevator => true do
20
- let(:company1) { mock_model(Company, :database => Apartment::Test.next_db).as_null_object }
21
- let(:company2) { mock_model(Company, :database => Apartment::Test.next_db).as_null_object }
19
+ shared_context "elevators", elevator: true do
20
+ let(:company1) { mock_model(Company, database: db1).as_null_object }
21
+ let(:company2) { mock_model(Company, database: db2).as_null_object }
22
22
 
23
- let(:database1) { company1.database }
24
- let(:database2) { company2.database }
23
+ let(:api) { Apartment::Database }
25
24
 
26
- let(:api) { Apartment::Database }
27
-
28
- before do
29
- Apartment.reset # reset all config
30
- Apartment.seed_after_create = false
31
- Apartment.use_schemas = true
32
- api.reload! # reload adapter
33
-
34
- api.create(database1)
35
- api.create(database2)
36
- end
25
+ before do
26
+ Apartment.reset # reset all config
27
+ Apartment.seed_after_create = false
28
+ Apartment.use_schemas = true
29
+ api.reload!(config)
30
+ api.create(db1)
31
+ api.create(db2)
32
+ end
37
33
 
38
- after do
39
- api.drop(database1)
40
- api.drop(database2)
34
+ after do
35
+ api.drop(db1)
36
+ api.drop(db2)
41
37
  end
42
38
  end
43
39
 
@@ -11,14 +11,8 @@ module Apartment
11
11
  extend ActiveSupport::Concern
12
12
 
13
13
  included do
14
- let(:db1){ Apartment::Test.next_db }
15
- let(:db2){ Apartment::Test.next_db }
16
- let(:connection){ ActiveRecord::Base.connection }
17
14
 
18
15
  before do
19
- Apartment::Database.reload!(config.symbolize_keys)
20
- ActiveRecord::Base.establish_connection config
21
-
22
16
  subject.create(db1)
23
17
  subject.create(db2)
24
18
  end
@@ -30,20 +24,10 @@ module Apartment
30
24
  # sometimes we manually drop these schemas in testing, don't care if we can't drop, hence rescue
31
25
  subject.drop(db1) rescue true
32
26
  subject.drop(db2) rescue true
33
-
34
- # This is annoying, but for each sublcass that establishes its own connection (ie Company for excluded models for connection based adapters)
35
- # a separate connection is maintained (clear_all_connections! doesn't appear to deal with these)
36
- # This causes problems because previous tests that established this connection could F up the next test, so we'll just remove them all for each test :(
37
- Apartment.excluded_models.each do |m|
38
- klass = m.constantize
39
- Apartment.connection_class.remove_connection(klass)
40
- klass.reset_table_name
41
- end
42
- ActiveRecord::Base.clear_all_connections!
43
27
  end
44
28
  end
45
29
 
46
- %w{subject config database_names default_database}.each do |method|
30
+ %w{subject database_names default_database}.each do |method|
47
31
  define_method method do
48
32
  raise "You must define a `#{method}` method in your host group"
49
33
  end unless defined?(method)
@@ -0,0 +1,47 @@
1
+ module Apartment
2
+ module Spec
3
+ module Setup
4
+
5
+ def self.included(base)
6
+ base.instance_eval do
7
+ let(:config){ database_config }
8
+
9
+ let(:db1){ Apartment::Test.next_db }
10
+ let(:db2){ Apartment::Test.next_db }
11
+ let(:connection){ ActiveRecord::Base.connection }
12
+
13
+ # This around ensures that we run these hooks before and after
14
+ # any before/after hooks defined in individual tests
15
+ # Otherwise these actually get run after test defined hooks
16
+ around(:each) do |example|
17
+ # before
18
+ Apartment::Database.reload!(config)
19
+ ActiveRecord::Base.establish_connection config
20
+
21
+ example.run
22
+
23
+ # after
24
+ Rails.configuration.database_configuration = {}
25
+ ActiveRecord::Base.clear_all_connections!
26
+
27
+ Apartment.excluded_models.each do |model|
28
+ klass = model.constantize
29
+
30
+ Apartment.connection_class.remove_connection(klass)
31
+ klass.clear_all_connections!
32
+ klass.reset_table_name
33
+ end
34
+
35
+ Apartment.reset
36
+ Apartment::Database.reload!
37
+ end
38
+ end
39
+ end
40
+
41
+ def database_config
42
+ db = example.metadata.fetch(:database, :postgresql)
43
+ Apartment::Test.config['connections'][db.to_s].symbolize_keys
44
+ end
45
+ end
46
+ end
47
+ end