Config apartment-gem for MySQL using structure.sql instead of schema.rb to create a new tenant
Asked Answered
E

1

8

I need View SQL and Stored Procedure in my Rails app so I have to change from schema.rb to structure.sql. This is my config in config/application.rb

config.active_record.schema_format = :sql

but then when I create a new record for an entity in seed.rb

Company.create(
        name: 'Google',
        subdomain: 'google'
      )

error happened

my_project/db/schema.rb doesn't exist yet

I don't know what is the problem. Did I miss something in cofig, somewhere still require schema.rb or I miss some rake task command? I just used

rake db:migrate db:test:prepare

follow this blog https://rietta.com/blog/2013/11/28/rails-and-sql-views-for-a-report/#setting-up-the-sql-view

UPDATE: I am using apartment-gem and Company entity is a Tenant.

Here is config in apartment.rb

Apartment.configure do |config|
  config.excluded_models = %w{ Company CommonField }
  config.tenant_names = lambda{ Company.pluck(:subdomain) }
  # ==> PostgreSQL only options
  config.use_schemas = true

  # Apartment can be forced to use raw SQL dumps instead of schema.rb for 
  # creating new schemas.
  # Use this when you are using some extra features in PostgreSQL that can't 
  # be respresented in
  # schema.rb, like materialized views etc. (only applies with use_schemas set 
  # to true).
  # (Note: this option doesn't use db/structure.sql, it creates SQL dump by 
  # executing pg_dump)
  #
  # config.use_sql = false
  # <== PostgreSQL only options
  config.prepend_environment = !Rails.env.production?
end

I try to change config.use_schemas to false then enable and set config.use_sql to true but it still not work. Maybe it's setting for PosrtgreSQL only.

So, have any setting for MySQL?

Ellita answered 8/5, 2017 at 2:1 Comment(1)
Could you provide the full error stack trace?Lopsided
M
1

the mysql2_adapter in gem apartment extend from abstract_adapter and it inherits the create method as below:

def create(tenant)
 run_callbacks :create do
  create_tenant(tenant)

  switch(tenant) do
   import_database_schema

   # Seed data if appropriate
   seed_data if Apartment.seed_after_create

   yield if block_given?
  end
 end
end

the import_database_schema method will throw the error: FileNotFound ... db/schema.rb doesn't exist yet if there's no such file schema.rb, so i guess when you decide to use structure.sql instead of schema.rb you deleted it.

i suggest 2 ways to fix:

  1. create an empty file schema.rb, that it.
  2. you still need the config use_schemas since that indicate gem apartment will use postgresql schemas and mysql use, however in case of mysql, if you use structure.sql, no need to import_database_schema at all, right ? so you can create new mysql adapter like below:
# your-app/lib/apartment/adapters/mysql2_structure_adapter.rb
require 'apartment/adapters/mysql2_adapter'

module Apartment
  module Tenant
    def self.mysql2_adapter(config)
      if Apartment.use_schemas
        Apartment.use_sql ?
          Adapters::Mysql2StructureAdapter.new(config) :
          Adapters::Mysql2SchemaAdapter.new(config)
      else
        Adapters::Mysql2Adapter.new(config)
      end
    end
  end

  module Adapters
    class Mysql2StructureAdapter < Mysql2SchemaAdapter
      def create(tenant)
        run_callbacks :create do
          create_tenant(tenant)

          switch(tenant) do
            # no need to import schema
            # import_database_schema

            # Seed data if appropriate
            seed_data if Apartment.seed_after_create

            yield if block_given?
          end
        end
      end
    end
  end
end

then load that adapter, also turn on both use_schemas and use_sql on initializer config

# config/initializers/apartment.rb
Apartment.configure do |config|
  # ...
  config.use_schemas = true
  config.use_sql = true
end
# ...
Dir[File.join(Rails.root, "lib", "apartment", "adapters", "**/*.rb")].each {|r| require r}
Morville answered 18/6, 2021 at 17:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.