# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 222 def primary_key(table_name) columns(table_name).detect { |col| col.type == :primary_key }.try(:name) end
class NullDBAdapter
Constants
- REGISTRATION_MUTEX
Register types only once to avoid ActiveRecord::TypeConflictError in ActiveRecord::Type::Registration#<=>
Attributes
Public Class Methods
A convenience method for integratinginto RSpec. See README for example of use.
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 5 def self.insinuate_into_spec(config) config.before :all do ActiveRecord::Base.establish_connection(:adapter => :nulldb) end config.after :all do ActiveRecord::Base.establish_connection(:test) end end
Recognized options:
:schema
-
path to the schema file, relative to Rails.root
:table_definition_class_name
-
table definition class
(e.g. ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition for Postgres) or nil.
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 20 def initialize(config={}) @log = StringIO.new @logger = Logger.new(@log) @last_unique_id = 0 @tables = {'schema_info' => new_table_definition(nil)} @indexes = Hash.new { |hash, key| hash[key] = [] } @schema_path = config.fetch(:schema){ "db/schema.rb" } @config = config.merge(:adapter => :nulldb) super *initialize_args @visitor ||= Arel::Visitors::ToSql.new self if defined?(Arel::Visitors::ToSql) if config[:table_definition_class_name] ActiveRecord::ConnectionAdapters::NullDBAdapter.send(:remove_const, 'TableDefinition') ActiveRecord::ConnectionAdapters::NullDBAdapter.const_set('TableDefinition', self.class.const_get(config[:table_definition_class_name])) end register_types end
Public Instance Methods
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 59 def adapter_name "NullDB" end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 226 def add_column(table_name, column_name, type, **options) super table_meta = @tables[table_name.to_s] return unless table_meta table_meta.column column_name, type, **options end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 113 def add_fk_constraint(*args) # NOOP end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 86 def add_index(table_name, column_names, **options) options[:unique] = false unless options.key?(:unique) column_names = Array.wrap(column_names).map(&:to_s) index, index_type, ignore = add_index_options(table_name, column_names, **options) if index.is_a?(ActiveRecord::ConnectionAdapters::IndexDefinition) @indexes[table_name] << index else # Rails < 6.1 @indexes[table_name] << IndexDefinition.new(table_name, index, (index_type == 'UNIQUE'), column_names, [], []) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 117 def add_pk_constraint(*args) # NOOP end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 235 def change_column(table_name, column_name, type, options = {}) table_meta = @tables[table_name.to_s] column = table_meta.columns.find { |column| column.name == column_name.to_s } return unless column column.type = type column.options = options if options end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 252 def change_column_default(table_name, column_name, default_or_changes) table_meta = @tables[table_name.to_s] column = table_meta.columns.find { |column| column.name == column_name.to_s } return unless column if default_or_changes.kind_of? Hash column.default = default_or_changes[:to] else column.default = default_or_changes end end
Inserts a checkpoint in the log. See also execution_log_since_checkpoint
.
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 55 def checkpoint! self.execution_log << Checkpoint.new end
Retrieve table columns as defined by the schema
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 135 def columns(table_name, name = nil) if @tables.size <= 1 ActiveRecord::Migration.verbose = false schema_path = if Pathname(@schema_path).absolute? @schema_path else File.join(NullDB.configuration.project_root, @schema_path) end Kernel.load(schema_path) end if table = @tables[table_name] table.columns.map do |col_def| col_args = default_column_arguments(col_def) ActiveRecord::ConnectionAdapters::NullDBAdapter::Column.new(*col_args) end else [] end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 67 def create_table(table_name, options = {}) table_definition = new_table_definition(self, table_name, options.delete(:temporary), options) unless options[:id] == false table_definition.primary_key(options[:primary_key] || "id") end yield table_definition if block_given? @tables[table_name.to_s] = table_definition end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 192 def delete(statement, name=nil, binds = []) with_entry_point(:delete) do super(statement, name).size end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 121 def enable_extension(*) # NOOP end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 166 def exec_query(statement, name = 'SQL', binds = [], options = {}) self.execution_log << Statement.new(entry_point, statement) EmptyResult.new end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 161 def execute(statement, name = nil) self.execution_log << Statement.new(entry_point, statement) NullObject.new end
A log of every statement that has been “executed” by this connection adapter instance.
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 42 def execution_log (@execution_log ||= []) end
A log of every statement that has been “executed” since the last time checkpoint!
was called, or since the connection was created.
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 48 def execution_log_since_checkpoint checkpoint_index = @execution_log.rindex(Checkpoint.new) checkpoint_index = checkpoint_index ? checkpoint_index + 1 : 0 @execution_log[(checkpoint_index..-1)] end
Retrieve table indexes as defined by the schema
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 157 def indexes(table_name, name = nil) @indexes[table_name] end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 177 def insert(statement, name = nil, primary_key = nil, object_id = nil, sequence_name = nil, binds = []) (object_id || next_unique_id).tap do with_entry_point(:insert) do super(statement, name, primary_key, object_id, sequence_name) end end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 102 def remove_index(table_name, column_name = nil, **options ) index_name = index_name_for_remove(table_name, column_name, options) index = @indexes[table_name].reject! { |index| index.name == index_name } end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 244 def rename_column(table_name, column_name, new_column_name) table_meta = @tables[table_name.to_s] column = table_meta.columns.find { |column| column.name == column_name.to_s } return unless column column.name = new_column_name end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 79 def rename_table(table_name, new_name) table_definition = @tables.delete(table_name.to_s) table_definition.name = new_name.to_s @tables[new_name.to_s] = table_definition end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 198 def select_all(statement, name=nil, binds = [], options = {}) with_entry_point(:select_all) do super(statement, name) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 204 def select_one(statement, name=nil, binds = []) with_entry_point(:select_one) do super(statement, name) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 171 def select_rows(statement, name = nil, binds = []) [].tap do self.execution_log << Statement.new(entry_point, statement) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 210 def select_value(statement, name=nil, binds = []) with_entry_point(:select_value) do super(statement, name) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 216 def select_values(statement, name=nil) with_entry_point(:select_values) do super(statement, name) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 63 def supports_migrations? true end
Retrieve the table names defined by the schema
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 126 def tables @tables.keys.map(&:to_s) end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 186 def update(statement, name=nil, binds = []) with_entry_point(:update) do super(statement, name) end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 130 def views [] # TODO: Implement properly if needed - This is new method in rails end
Protected Instance Methods
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 267 def select(statement, name = nil, binds = [], prepare: nil, async: nil) EmptyResult.new.tap do |r| r.bind_column_meta(columns_for(name)) self.execution_log << Statement.new(entry_point, statement) end end
Private Instance Methods
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 276 def columns_for(table_name) table_meta = @tables[table_name] return [] unless table_meta table_meta.columns end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 325 def default_column_arguments(col_def) [ col_def.name.to_s, col_def.default.present? ? col_def.default.to_s : nil, sql_type_definition(col_def), col_def.null.nil? || col_def.null ] end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 296 def entry_point Thread.current[:entry_point] end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 310 def includes_column? false end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 342 def initialize_args [nil, @logger, @config] end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 314 def new_table_definition(adapter = nil, table_name = nil, is_temporary = nil, options = {}) case ::ActiveRecord::VERSION::MAJOR when 6, 7 TableDefinition.new(self, table_name, temporary: is_temporary, options: options.except(:id)) when 5 TableDefinition.new(table_name, is_temporary, options.except(:id), nil) else raise "Unsupported ActiveRecord version #{::ActiveRecord::VERSION::STRING}" end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 282 def next_unique_id @last_unique_id += 1 end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 350 def register_types REGISTRATION_MUTEX.synchronize do return if self.class.types_registered self.class.types_registered = true end ActiveRecord::Type.register( :primary_key, ActiveModel::Type::Integer, adapter: adapter_name, override: true ) ActiveRecord::Type.add_modifier({ array: true }, DummyOID, adapter: :nulldb) ActiveRecord::Type.add_modifier({ range: true }, DummyOID, adapter: :nulldb) end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 334 def sql_type_definition(col_def) ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new( type: col_def.type, sql_type: col_def.type.to_s, limit: col_def.limit ) end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 286 def with_entry_point(method) if entry_point.nil? with_thread_local_variable(:entry_point, method) do yield end else yield end end
# File lib/active_record/connection_adapters/nulldb_adapter/core.rb, line 300 def with_thread_local_variable(name, value) old_value = Thread.current[name] Thread.current[name] = value begin yield ensure Thread.current[name] = old_value end end