Class: ActiveRecord::Tenanted::DatabaseAdapters::SQLite
- Inherits:
-
Object
- Object
- ActiveRecord::Tenanted::DatabaseAdapters::SQLite
- Defined in:
- lib/active_record/tenanted/database_adapters/sqlite.rb
Overview
TODO: This still feels to me like it’s not quite right. I think we could further refactor this by:
1. Moving tenant_databases and validate_tenant_name to BaseConfig, and subclassing it for
each database
2. Moving create_database, drop_database, database_exist?, database_ready?,
acquire_ready_lock, ensure_database_directory_exists, and database_path to the SQLite
connection adapter, possibly into Rails
3. Moving test_workerize and path_for to be SQLite connection adapter class methods,
possibly into Rails
Instance Attribute Summary collapse
-
#db_config ⇒ Object
readonly
Returns the value of attribute db_config.
Instance Method Summary collapse
- #acquire_ready_lock(&block) ⇒ Object
- #create_database ⇒ Object
- #database_exist? ⇒ Boolean
- #database_path ⇒ Object
- #database_ready? ⇒ Boolean
- #drop_database ⇒ Object
- #ensure_database_directory_exists ⇒ Object
-
#initialize(db_config) ⇒ SQLite
constructor
A new instance of SQLite.
-
#path_for(database) ⇒ Object
A sqlite database path can be a file path or a URI (either relative or absolute).
- #tenant_databases ⇒ Object
- #test_workerize(db, test_worker_id) ⇒ Object
- #validate_tenant_name(tenant_name) ⇒ Object
Constructor Details
#initialize(db_config) ⇒ SQLite
Returns a new instance of SQLite.
20 21 22 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 20 def initialize(db_config) @db_config = db_config end |
Instance Attribute Details
#db_config ⇒ Object (readonly)
Returns the value of attribute db_config.
18 19 20 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 18 def db_config @db_config end |
Instance Method Details
#acquire_ready_lock(&block) ⇒ Object
63 64 65 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 63 def acquire_ready_lock(&block) ActiveRecord::Tenanted::Mutex::Ready.lock(database_path, &block) end |
#create_database ⇒ Object
43 44 45 46 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 43 def create_database ensure_database_directory_exists FileUtils.touch(database_path) end |
#database_exist? ⇒ Boolean
55 56 57 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 55 def database_exist? File.exist?(database_path) end |
#database_path ⇒ Object
76 77 78 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 76 def database_path path_for(db_config.database) end |
#database_ready? ⇒ Boolean
59 60 61 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 59 def database_ready? File.exist?(database_path) && !ActiveRecord::Tenanted::Mutex::Ready.locked?(database_path) end |
#drop_database ⇒ Object
48 49 50 51 52 53 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 48 def drop_database # Remove the SQLite database file and associated files FileUtils.rm_f(database_path) FileUtils.rm_f("#{database_path}-wal") # Write-Ahead Logging file FileUtils.rm_f("#{database_path}-shm") # Shared Memory file end |
#ensure_database_directory_exists ⇒ Object
67 68 69 70 71 72 73 74 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 67 def ensure_database_directory_exists return unless database_path database_dir = File.dirname(database_path) unless File.directory?(database_dir) FileUtils.mkdir_p(database_dir) end end |
#path_for(database) ⇒ Object
A sqlite database path can be a file path or a URI (either relative or absolute). We can’t parse it as a standard URI in all circumstances, though, see sqlite.org/uri.html
103 104 105 106 107 108 109 110 111 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 103 def path_for(database) if database.start_with?("file:/") URI.parse(database).path elsif database.start_with?("file:") URI.parse(database.sub(/\?.*$/, "")).opaque else database end end |
#tenant_databases ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 24 def tenant_databases glob = path_for(db_config.database_for("*")) scanner = Regexp.new(path_for(db_config.database_for("(.+)"))) Dir.glob(glob).filter_map do |path| result = path.scan(scanner).flatten.first if result.nil? Rails.logger.warn "ActiveRecord::Tenanted: Cannot parse tenant name from filename #{path.inspect}" end result end end |
#test_workerize(db, test_worker_id) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 80 def test_workerize(db, test_worker_id) test_worker_suffix = "_#{test_worker_id}" if db.start_with?("file:") && db.include?("?") db.sub(/(\?.*)$/, "#{test_worker_suffix}\\1") else # This check is needed because of https://github.com/rails/rails/pull/55769 adding # replicas to the parallelization setup by using `include_hidden: true` which pulls in # the BaseConfig. We don't want to double-suffix the database name. # # TODO: Ideally we should have finer-grained filtering of database configurations in Rails # (other than simply hidden or not-hidden). if db.end_with?(test_worker_suffix) db else db + test_worker_suffix end end end |
#validate_tenant_name(tenant_name) ⇒ Object
37 38 39 40 41 |
# File 'lib/active_record/tenanted/database_adapters/sqlite.rb', line 37 def validate_tenant_name(tenant_name) if tenant_name.match?(%r{[/'"`]}) raise BadTenantNameError, "Tenant name contains an invalid character: #{tenant_name.inspect}" end end |