Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rails 6.1.alpha support #638

Open
jean-francois-labbe opened this issue Feb 12, 2020 · 4 comments
Open

rails 6.1.alpha support #638

jean-francois-labbe opened this issue Feb 12, 2020 · 4 comments

Comments

@jean-francois-labbe
Copy link

Steps to reproduce

I'm trying to use apartment with rails 6.1.alpha (rails-master) tests are failing and I don't understand the issue yet.

The error is:

ActiveRecord::StatementInvalid:
PG::UndefinedTable: ERROR:  relation "schema_migrations" does not exist
LINE 1: SELECT "schema_migrations"."version" FROM "schema_migrations...

When I try to debug the application the only difference I see between rails-6.0 and rails-master
is during migrations

With Rails-6.0 it executes:

CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "birthdate" timestamp, "sex" character varying)
CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY)
SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC

with Rails-6.1.alpha (master) it executes:

CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "birthdate" timestamp, "sex" character varying)
SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC

That would justify the error, but I don't understand why it doesn't create the schema_migrations database

  • use_schemas: true

During tests 2 dbs are created, the first one is perfectly created, but the second one is missing the tables schema_migrations and ar_internal_metadata.

After some debugging here is what I found.

This is the sql log of the first database creation. It is here just to ease comparison between the two dbs creation.

CREATE SCHEMA "db1"
CREATE EXTENSION IF NOT EXISTS "plpgsql"
DROP TABLE IF EXISTS "books" CASCADE
CREATE TABLE "books" ("id" bigserial primary key, "name" character varying, "pages" integer, "published" timestamp)
DROP TABLE IF EXISTS "companies" CASCADE
CREATE TABLE "companies" ("id" bigserial primary key, "dummy" boolean, "database" character varying)
DROP TABLE IF EXISTS "delayed_jobs" CASCADE
CREATE TABLE "delayed_jobs" ("id" bigserial primary key, "priority" integer DEFAULT 0, "attempts" integer DEFAULT 0, "handler" text, "last_error" text, "run_at" timestamp, "locked_at" timestamp, "failed_at" timestamp, "locked_by" character varying, "created_at" timestamp, "updated_at" timestamp, "queue" character varying)
CREATE  INDEX  "delayed_jobs_priority" ON "delayed_jobs"  ("priority", "run_at")
DROP TABLE IF EXISTS "public_tokens" CASCADE
CREATE TABLE "public_tokens" ("id" serial NOT NULL PRIMARY KEY, "token" character varying, "user_id" integer)
DROP TABLE IF EXISTS "users" CASCADE
CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "birthdate" timestamp, "sex" character varying)
CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY)
SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
INSERT INTO "schema_migrations" (version) VALUES (20180415260934)
INSERT INTO "schema_migrations" (version) VALUES
(20110613152810),
(20111202022214);

CREATE TABLE "ar_internal_metadata" ("key" character varying NOT NULL PRIMARY KEY, "value" character varying, "created_at" timestamp(6) NOT NULL, "updated_at" timestamp(6) NOT NULL)
SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", "environment"], ["LIMIT", 1]]
BEGIN
INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key"  [["key", "environment"], ["value", "test"], ["created_at", "2020-02-12 21:09:41.525485"], ["updated_at", "2020-02-12 21:09:41.525485"]]
COMMIT
BEGIN
INSERT INTO "companies" ("database") VALUES ($1) RETURNING "id"  [["database", "db1"]]
COMMIT

Second db is where troubles are.

CREATE SCHEMA "db2"
CREATE EXTENSION IF NOT EXISTS "plpgsql"
DROP TABLE IF EXISTS "books" CASCADE
CREATE TABLE "books" ("id" bigserial primary key, "name" character varying, "pages" integer, "published" timestamp)
DROP TABLE IF EXISTS "companies" CASCADE
CREATE TABLE "companies" ("id" bigserial primary key, "dummy" boolean, "database" character varying)
DROP TABLE IF EXISTS "delayed_jobs" CASCADE
CREATE TABLE "delayed_jobs" ("id" bigserial primary key, "priority" integer DEFAULT 0, "attempts" integer DEFAULT 0, "handler" text, "last_error" text, "run_at" timestamp, "locked_at" timestamp, "failed_at" timestamp, "locked_by" character varying, "created_at" timestamp, "updated_at" timestamp, "queue" character varying)
CREATE  INDEX  "delayed_jobs_priority" ON "delayed_jobs"  ("priority", "run_at")
DROP TABLE IF EXISTS "public_tokens" CASCADE
CREATE TABLE "public_tokens" ("id" serial NOT NULL PRIMARY KEY, "token" character varying, "user_id" integer)
DROP TABLE IF EXISTS "users" CASCADE
CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "birthdate" timestamp, "sex" character varying)

[22, 31] in rails-39d3c9bcacb4/activerecord/lib/active_record/schema_migration.rb
   24: 
   25:       def create_table
   26:         byebug
=> 27:         unless table_exists?
   28:           version_options = connection.internal_string_options_for_primary_key
   29: 
   30:           connection.create_table(table_name, id: false) do |t|
   31:             t.string :version, **version_options
(byebug) ActiveRecord::Base.connection.schema_search_path
"\"db2\""
(byebug) table_exists?
true
(byebug) table_name
"schema_migrations"
(byebug) ActiveRecord::Base.connection.tables
["books", "companies", "delayed_jobs", "public_tokens", "users"]
(byebug) ActiveRecord::Base.connection.data_source_exists?(table_name)
false
(byebug) ActiveRecord::Base.connection.schema_cache.data_source_exists?(table_name)
true

(byebug) continue

SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
DROP SCHEMA "db1" CASCADE
DROP SCHEMA "db2" CASCADE
DELETE FROM "companies"
    clears the ActiveRecord::QueryCache after switching databases (FAILED - 1)

Failures:

  1) query caching when use_schemas = true clears the ActiveRecord::QueryCache after switching databases
     Failure/Error:
       ActiveRecord::Schema.define(version: 2018_04_15_260934) do
       
         # These are extensions that must be enabled in order to support this database
         enable_extension "plpgsql"
       
         create_table "books", force: :cascade do |t|
           t.string "name"
           t.integer "pages"
           t.datetime "published"
         end
     
     ActiveRecord::StatementInvalid:
       PG::UndefinedTable: ERROR:  relation "schema_migrations" does not exist
       LINE 1: SELECT "schema_migrations"."version" FROM "schema_migrations...

create_table is defined in schema_migration.rb

table_exists? implementation is in model_schema.rb

def table_exists?
  connection.schema_cache.data_source_exists?(table_name)
end

In rails 6.0 schema_migration.rb had a method table_exists? defined in it, the implementation was:

def table_exists?
  connection.table_exists?(table_name)
end

It was removed in this commit rails/rails@c5ecc33#diff-a15c218db8b9dd9f84a75d9a3894db56

@cristianrosu
Copy link

How are you able to use it with Rails 6? I installed the gem but then the application crashed and I can't even run the apartment generator

@jean-francois-labbe
Copy link
Author

@cristianrosu this repo is no more maintained. You need to use this one now.

Use gem 'ros-apartment', require: 'apartment' in your Gemfile and it should be working

Ps: If you're working on a new project, you may think twice before use this gem, it may not be the best solution, if you have a lot of tenants, as the creators themselves explain here.

I use it with Postgresql schemas and few tenants, it's working great.

@cristianrosu
Copy link

@jean-francois-labbe I was not aware of that fork, thanks a lot, looks promising!

I won't have many tenants but it's important to separate data per account. It will work good for now. Thanks!

@jjb
Copy link

jjb commented Sep 21, 2022

Above link is dead, working link is here: https://medium.com/infinite-monkeys/our-multi-tenancy-journey-with-postgres-schemas-and-apartment-6ecda151a21f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants