activerecord-nulldb-adapter-1.1.1/0000755000004100000410000000000014716761556017132 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/.gitignore0000644000004100000410000000031114716761556021115 0ustar www-datawww-data# generated coverage coverage coverage.data # docs rdoc doc .yardoc # bundler .bundle *.lock vendor # gem pkg *.gem # mac os specific .DS_Store # vim *.swp # rvm .rvmrc .ruby-* # ginger .ginger activerecord-nulldb-adapter-1.1.1/CHANGES.md0000644000004100000410000000545514716761556020535 0ustar www-datawww-dataUnreleased ---------- 1.1.1 (20214-11-14) - Fix syntax error on 2.7 and 3.0. 1.1.0 (2024-11-14) ----------- - Add support to Rails 8 #136 - *Breaking* Drop support to Ruby 2.5, 2.6 - *Breaking* Drop support to Rails 6.0 (keep 6.1) 1.0.1 (2023-10-16) ----------- - Alias enum field #122 1.0.0 (2023-10-16) ----------- - Add support to Rails 7.1 #124 0.9.0 (2023-03-10) ----------- - Add support to BigSerial #119 - Add support to hstore #118 - Support Postgres type modifiers #117 0.8.0 (2022-10-28) ----------- - Add support for Rails 7. #111 #112 0.7.0 (2021-01-18) ----------- - Add support to Rails 6.1 #106 0.6.0 (2021-01-08) ----------- - *Breaking* Finish dropping support to Rails <= 5.1 by removing custom code for these versions. #101 0.5.0 (2020-10-15) ----------- - *Breaking* Drop support to Ruby 2.2, 2.3, 2.4 - *Breaking* Drop support to Rails 2.X, 3.X, 4.X, 5.0, 5.1 - Drop support to old versions of Ruby and Rails. #96 - Added support for postgres column types included jsonb and ability to delete columns #94 0.4.0 (2019-07-22) ----------- - *Breaking* Drop support to Ruby 1.9 - Add support for ActiveRecord 6.0 #90 - Prevent ActiveRecord::Tasks::DatabaseNotSupported #88 0.3.9 (2018-07-07) ----------- - Fix broken count - Avoid monkey patching Schema.define - Support ruby 2.4 (drop support for ruby 2.1 and rails 3.0/3.1) - Support custom TableDefinition (useful for postgres) 0.3.8 (2018-02-06) ----------- - Adds support for ActiveRecord Edge (6.0) 0.3.7 (2017-06-04) ----------- - Adds support for ActiveRecord 5.1/5.2. - Support limit and null 0.3.6 (2016-11-23) ----------- - Adds support for ActiveRecord 5.0. 0.3.5 (2016-09-26) ----------- - Adds support for #cast_values on EmptyResult instance. 0.3.4 (2016-08-10) ----------- - Adds support for Postgres-specific 'enable_extension' 0.3.3 (2016-08-01) ----------- - Adds support for ActiveRecord 4.2. - Deprecates support for MRI 2.0.0. 0.3.2 (2016-01-25) ----------- - Deprecates support for MRI 1.9.3 and adds support for 2.3.x. - Fixes :string column type fetching for AR 4.1. 0.3.1 (2014-02-17) ----------- - Removes accidental dependency on iconv. Fixing JRuby support. 0.3.0 (2014-01-31) ----------- - Drops 1.8.7 support. - Adds support for Ruby 2.0, 2.1 and ActiveRecord 4. - Fixes ActiveRecord 2.3 support on Ruby 2 and up. - Misc small fixes 0.2.1 (2010-09-01) ----------- - Updated Rails 3 support so that nulldb works against AR 3.0.0. - Add support for RSpec 2. 0.2.0 (2010-03-20) ----------- - Rails 3 support. All specs pass against ActiveRecord 3.0.0.beta. 0.1.1 (2010-03-15) ----------- - Released as activerecord-nulldb-adapter gem. 0.1.0 (2010-03-02) ----------- - Released as nulldb gem, with some bug fixes. 0.0.2 (2007-05-31) ----------- - Moved to Rubyforge 0.0.1 (2007-02-18) ----------- - Initial Release activerecord-nulldb-adapter-1.1.1/.github/0000755000004100000410000000000014716761556020472 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/.github/workflows/0000755000004100000410000000000014716761556022527 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/.github/workflows/ruby.yml0000644000004100000410000000341714716761556024240 0ustar www-datawww-dataname: build on: [push, pull_request] jobs: test: strategy: fail-fast: false matrix: gemfile: [ activerecord_6.1, activerecord_7.0, activerecord_7.1, activerecord_7.2, activerecord_8.0, activerecord_master, ] ruby: ["2.7", "3.0", "3.1", "3.2", "3.3", "jruby-9.3.1.0"] exclude: - ruby: "jruby-9.3.1.0" gemfile: "activerecord_7.0" - ruby: "jruby-9.3.1.0" gemfile: "activerecord_7.1" - ruby: "2.7" gemfile: "activerecord_7.2" - ruby: "2.8" gemfile: "activerecord_7.2" - ruby: "3.0" gemfile: "activerecord_7.2" - ruby: "jruby-9.3.1.0" gemfile: "activerecord_7.2" - ruby: "2.7" gemfile: "activerecord_8.0" - ruby: "2.8" gemfile: "activerecord_8.0" - ruby: "3.0" gemfile: "activerecord_8.0" - ruby: "3.1" gemfile: "activerecord_8.0" - ruby: "jruby-9.3.1.0" gemfile: "activerecord_8.0" - ruby: "2.7" gemfile: "activerecord_master" - ruby: "2.8" gemfile: "activerecord_master" - ruby: "3.0" gemfile: "activerecord_master" - ruby: "3.1" gemfile: "activerecord_master" - ruby: "jruby-9.3.1.0" gemfile: "activerecord_master" runs-on: ubuntu-latest env: BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - run: bundle exec rake activerecord-nulldb-adapter-1.1.1/lib/0000755000004100000410000000000014716761556017700 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/tasks/0000755000004100000410000000000014716761556021025 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/tasks/database.rake0000644000004100000410000000145414716761556023441 0ustar www-datawww-data# Sadly, we have to monkeypatch Rake because all of the Rails database tasks are # hardcoded for specific adapters, with no extension points (!) Rake::TaskManager.class_eval do def remove_task(task_name) @tasks.delete(task_name.to_s) end end def remove_task(task_name) Rake.application.remove_task(task_name) end def wrap_task(task_name, &wrapper) wrapped_task = Rake::Task[task_name] remove_task(Rake::Task.scope_name(Rake.application.current_scope, task_name)) task(task_name) do wrapper.call(wrapped_task) end end namespace :db do namespace :test do wrap_task :purge do |wrapped_task| if ActiveRecord::Base.configurations["test"]["adapter"] == "nulldb" # NO-OP else wrapped_task.invoke end end end end activerecord-nulldb-adapter-1.1.1/lib/nulldb_rspec.rb0000644000004100000410000000454414716761556022710 0ustar www-datawww-datarequire 'active_record/connection_adapters/nulldb_adapter' module NullDB module RSpec end end module NullDB::RSpec::NullifiedDatabase NullDBAdapter = ActiveRecord::ConnectionAdapters::NullDBAdapter class HaveExecuted def initialize(entry_point) @entry_point = entry_point end def matches?(connection) log = connection.execution_log_since_checkpoint if @entry_point == :anything not log.empty? else log.include?(NullDBAdapter::Statement.new(@entry_point)) end end def description "connection should execute #{@entry_point} statement" end def failure_message " did not execute #{@entry_point} statement when it should have" end def negative_failure_message " executed #{@entry_point} statement when it should not have" end end def self.globally_nullify_database block = lambda { |config| nullify_database(config) } if defined?(RSpec) RSpec.configure(&block) else Spec::Runner.configure(&block) end end def self.contextually_nullify_database(context) nullify_database(context) end # A matcher for asserting that database statements have (or have not) been # executed. Usage: # # ActiveRecord::Base.connection.should have_executed(:insert) # # The types of statement that can be matched mostly mirror the public # operations available in # ActiveRecord::ConnectionAdapters::DatabaseStatements: # - :select_one # - :select_all # - :select_value # - :insert # - :update # - :delete # - :execute # # There is also a special :anything symbol that will match any operation. def have_executed(entry_point) HaveExecuted.new(entry_point) end private def self.included(other) if nullify_contextually?(other) contextually_nullify_database(other) else globally_nullify_database end end def self.nullify_contextually?(other) if defined?(RSpec) other < RSpec::Core::ExampleGroup else other.is_a? Spec::ExampleGroup end end def self.nullify_database(receiver) receiver.before :all do ActiveRecord::Base.establish_connection(:adapter => :nulldb) end receiver.before :each do ActiveRecord::Base.connection.checkpoint! end receiver.after :all do ActiveRecord::Base.establish_connection(:test) end end end activerecord-nulldb-adapter-1.1.1/lib/nulldb/0000755000004100000410000000000014716761556021160 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/nulldb/arel_compiler.rb0000644000004100000410000000013614716761556024322 0ustar www-datawww-datamodule Arel module SqlCompiler class NullDBCompiler < GenericCompiler end end end activerecord-nulldb-adapter-1.1.1/lib/nulldb/rails.rb0000644000004100000410000000045414716761556022622 0ustar www-datawww-datarequire 'nulldb/core' # Need to defer calling Rails.root because when bundler loads, Rails.root is nil NullDB.configure {|ndb| def ndb.project_root;Rails.root;end} ActiveRecord::Tasks::DatabaseTasks.register_task(/nulldb/, ActiveRecord::Tasks::NullDBDatabaseTasks) if defined?(ActiveRecord::Tasks) activerecord-nulldb-adapter-1.1.1/lib/nulldb/core.rb0000644000004100000410000000166514716761556022445 0ustar www-datawww-datarequire 'active_support' require 'active_support/deprecation' require 'active_record/connection_adapters/nulldb_adapter' module NullDB class Configuration < Struct.new(:project_root); end class << self def configure @configuration = Configuration.new.tap {|c| yield c} end def configuration if @configuration.nil? raise "NullDB not configured. Require a framework, ex 'nulldb/rails'" end @configuration end def nullify(options={}) begin @prev_connection = ActiveRecord::Base.connection_pool.try(:spec) rescue ActiveRecord::ConnectionNotEstablished end ActiveRecord::Base.establish_connection(options.merge(:adapter => :nulldb)) end def restore if @prev_connection ActiveRecord::Base.establish_connection(@prev_connection.config) end end def checkpoint ActiveRecord::Base.connection.checkpoint! end end end activerecord-nulldb-adapter-1.1.1/lib/nulldb/version.rb0000644000004100000410000000004614716761556023172 0ustar www-datawww-datamodule NullDB VERSION = "1.1.1" end activerecord-nulldb-adapter-1.1.1/lib/nulldb/extensions.rb0000644000004100000410000000103414716761556023702 0ustar www-datawww-dataunless respond_to?(:tap) class Object def tap yield self self end end end unless respond_to?(:try) class Object def try(*a, &b) if a.empty? && block_given? yield self else __send__(*a, &b) end end end class NilClass def try(*args); nil; end end end class ActiveRecord::Base # Instantiate a new NullDB connection. Used by ActiveRecord internally. def self.nulldb_connection(config) ActiveRecord::ConnectionAdapters::NullDBAdapter.new(config) end endactiverecord-nulldb-adapter-1.1.1/lib/active_record/0000755000004100000410000000000014716761556022511 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/active_record/tasks/0000755000004100000410000000000014716761556023636 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/active_record/tasks/nulldb_database_tasks.rb0000644000004100000410000000064614716761556030502 0ustar www-datawww-dataclass ActiveRecord::Tasks::NullDBDatabaseTasks def initialize(configuration) @configuration = configuration end def create(master_established = false) # NO-OP end def drop # NO-OP end def purge # NO-OP end def structure_dump(filename, extra_flags) # NO-OP end def structure_load(filename, extra_flags) # NO-OP end def clear_active_connections! # NO-OP end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/0000755000004100000410000000000014716761556026533 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/quoting.rb0000644000004100000410000000036214716761556030547 0ustar www-datawww-datamodule ActiveRecord module ConnectionAdapters module Quoting extend ActiveSupport::Concern module ClassMethods def quote_column_name(column_name) "'#{column_name}'" end end end end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter.rb0000644000004100000410000000231714716761556032043 0ustar www-datawww-datarequire 'logger' require 'stringio' require 'singleton' require 'pathname' require 'active_support' require 'active_record/connection_adapters/abstract_adapter' require 'nulldb/core' require 'nulldb/extensions' require 'active_record/connection_adapters/quoting' require 'active_record/connection_adapters/nulldb_adapter/core' require 'active_record/connection_adapters/nulldb_adapter/statement' require 'active_record/connection_adapters/nulldb_adapter/checkpoint' require 'active_record/connection_adapters/nulldb_adapter/column' require 'active_record/connection_adapters/nulldb_adapter/configuration' require 'active_record/connection_adapters/nulldb_adapter/empty_result' require 'active_record/connection_adapters/nulldb_adapter/index_definition' require 'active_record/connection_adapters/nulldb_adapter/null_object' require 'active_record/connection_adapters/nulldb_adapter/table_definition' require 'active_record/tasks/nulldb_database_tasks' if defined?(ActiveRecord::Tasks) module ActiveRecord module ConnectionAdapters if ActiveRecord::VERSION::STRING >= '7.2' register 'nulldb', 'ActiveRecord::ConnectionAdapters::NullDBAdapter', 'active_record/connection_adapters/nulldb_adapter' end end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/0000755000004100000410000000000014716761556031513 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/checkpoint.rb0000644000004100000410000000032414716761556034166 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class Checkpoint < Statement def initialize super(:checkpoint, "") end def ==(other) self.class == other.class end end end ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/empty_result.rbactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/empty_result.0000644000004100000410000000124314716761556034250 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class EmptyResult < Array attr_reader :column_types def bind_column_meta(columns) @columns = columns return if columns.empty? @column_types = columns.reduce({}) do |ctypes, col| ctypes[col.name] = ActiveRecord::Type.lookup(col.type) ctypes end end def columns @columns ||= [] end def column_types @column_types ||= {} end def cast_values(type_overrides = nil) rows end def rows [] end def >(num) rows.size > num end def includes_column?(name) false end end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/statement.rb0000644000004100000410000000045514716761556034050 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class Statement attr_reader :entry_point, :content def initialize(entry_point, content = "") @entry_point, @content = entry_point, content end def ==(other) self.entry_point == other.entry_point end end end ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/configuration.rbactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/configuration0000644000004100000410000000016314716761556034305 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class Configuration < Struct.new(:project_root); end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/column.rb0000644000004100000410000000017414716761556033337 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class Column < ::ActiveRecord::ConnectionAdapters::Column end end ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/null_object.rbactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/null_object.r0000644000004100000410000000025414716761556034177 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class NullObject def method_missing(*args, &block) nil end def to_a [] end end end ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/table_definition.rbactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/table_definit0000644000004100000410000000153414716761556034232 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition attr_accessor :name alias_method :enum, :string alias_method :uuid, :string alias_method :citext, :text alias_method :interval, :text alias_method :geometry, :text alias_method :serial, :integer alias_method :bigserial, :integer alias_method :inet, :string alias_method :jsonb, :json if method_defined? :json alias_method :hstore, :json def unique_constraint(*args, **kwargs, &block); end if ::ActiveRecord::VERSION::MAJOR >= 7 && ::ActiveRecord::VERSION::MINOR >= 1 # Avoid check for option validity def create_column_definition(name, type, options) ActiveRecord::ConnectionAdapters::ColumnDefinition.new(name, type, options) end end end end activerecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/core.rb0000644000004100000410000002615114716761556032775 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter # A convenience method for integratinginto RSpec. See README for example of # use. 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. 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 # A log of every statement that has been "executed" by this connection adapter # instance. 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. 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 # Inserts a checkpoint in the log. See also #execution_log_since_checkpoint. def checkpoint! self.execution_log << Checkpoint.new end def adapter_name "NullDB" end def supports_migrations? true end 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 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 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 # Rails 6.1+ if ActiveRecord::VERSION::MAJOR >= 7 || (ActiveRecord::VERSION::MAJOR >= 6 and ActiveRecord::VERSION::MINOR > 0) 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 else def remove_index(table_name, options = {} ) index_name = index_name_for_remove(table_name, options) index = @indexes[table_name].reject! { |index| index.name == index_name } end end def add_fk_constraint(*args) # NOOP end def add_pk_constraint(*args) # NOOP end def enable_extension(*) # NOOP end # Retrieve the table names defined by the schema def tables @tables.keys.map(&:to_s) end def views [] # TODO: Implement properly if needed - This is new method in rails end # Retrieve table columns as defined by the schema 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 # Retrieve table indexes as defined by the schema def indexes(table_name, name = nil) @indexes[table_name] end def execute(statement, name = nil) self.execution_log << Statement.new(entry_point, statement) NullObject.new end def exec_query(statement, name = 'SQL', binds = [], options = {}) internal_exec_query(statement, name, binds, **options) end def internal_exec_query(statement, name = 'SQL', binds = [], prepare: false, async: false) self.execution_log << Statement.new(entry_point, statement) EmptyResult.new end def select_rows(statement, name = nil, binds = [], async: false) [].tap do self.execution_log << Statement.new(entry_point, statement) end end def insert(statement, name = nil, primary_key = nil, object_id = nil, sequence_name = nil, binds = [], returning: nil) with_entry_point(:insert) do super(statement, name, primary_key, object_id, sequence_name) end result = object_id || next_unique_id returning ? [result] : result end alias :create :insert def update(statement, name=nil, binds = []) with_entry_point(:update) do super(statement, name) end end def delete(statement, name=nil, binds = []) with_entry_point(:delete) do super(statement, name) end end def select_all(statement, name=nil, binds = [], options = {}) with_entry_point(:select_all) do super(statement, name) end end def select_one(statement, name=nil, binds = []) with_entry_point(:select_one) do super(statement, name) end end def select_value(statement, name=nil, binds = []) with_entry_point(:select_value) do super(statement, name) end end def select_values(statement, name=nil) with_entry_point(:select_values) do super(statement, name) end end def primary_key(table_name) columns(table_name).detect { |col| col.type == :primary_key }.try(:name) end 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 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 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 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 ### Rails 8.0+ ### def perform_query(raw_connection, statement, binds, type_casted_binds, prepare:, notification_payload:, batch:) self.execution_log << Statement.new(entry_point, statement) NullObject.new end def affected_rows(raw_result) 0 end def valid_column_definition_options super + [:array, :using, :cast_as, :as, :type, :enum_type, :stored, :srid] end READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp( :close, :declare, :fetch, :move, :set, :show ) # :nodoc: private_constant :READ_QUERY def write_query?(sql) # :nodoc: !READ_QUERY.match?(sql) rescue ArgumentError # Invalid encoding !READ_QUERY.match?(sql.b) end def reconnect true end ### Rails 8.0+ ### protected def select(statement, name = nil, binds = [], prepare: nil, async: nil, allow_retry: nil) EmptyResult.new.tap do |r| r.bind_column_meta(columns_for(name)) self.execution_log << Statement.new(entry_point, statement) end end private def columns_for(table_name) table_meta = @tables[table_name] return [] unless table_meta table_meta.columns end def next_unique_id @last_unique_id += 1 end def with_entry_point(method) if entry_point.nil? with_thread_local_variable(:entry_point, method) do yield end else yield end end def entry_point Thread.current[:entry_point] end 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 def includes_column? false end def new_table_definition(adapter = nil, table_name = nil, is_temporary = nil, options = {}) case ::ActiveRecord::VERSION::MAJOR when 6, 7, 8 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 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 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 def initialize_args [nil, @logger, @config] end # Register types only once to avoid ActiveRecord::TypeConflictError # in ActiveRecord::Type::Registration#<=> REGISTRATION_MUTEX = Mutex.new 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 class << self attr_accessor :types_registered end class DummyOID < ActiveModel::Type::Value attr_reader :subtype def initialize(*args) @subtype = args.first end end end ././@LongLink0000644000000000000000000000015300000000000011602 Lustar rootrootactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/index_definition.rbactiverecord-nulldb-adapter-1.1.1/lib/active_record/connection_adapters/nulldb_adapter/index_definit0000644000004100000410000000023314716761556034245 0ustar www-datawww-dataclass ActiveRecord::ConnectionAdapters::NullDBAdapter class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders); end end activerecord-nulldb-adapter-1.1.1/lib/nulldb.rb0000644000004100000410000000005514716761556021505 0ustar www-datawww-datarequire 'nulldb/core' require 'nulldb/rails' activerecord-nulldb-adapter-1.1.1/lib/activerecord-nulldb-adapter.rb0000644000004100000410000000002114716761556025564 0ustar www-datawww-datarequire 'nulldb' activerecord-nulldb-adapter-1.1.1/Appraisals0000644000004100000410000000104014716761556021147 0ustar www-datawww-dataappraise "activerecord-5.2" do gem "activerecord", "~> 5.2.0" end appraise "activerecord-6.0" do gem "activerecord", "~> 6.0.0" end appraise "activerecord-7.0" do gem "activerecord", "~> 7.0.0" end appraise "activerecord-7.1" do gem "activerecord", "~> 7.1.0" end appraise "activerecord-7.2" do gem "activerecord", "~> 7.2.0" end appraise "activerecord-8.0" do gem "activerecord", github: 'rails/rails', branch: "8-0-stable" end appraise "activerecord-master" do gem "activerecord", github: 'rails/rails', branch: :main end activerecord-nulldb-adapter-1.1.1/spec/0000755000004100000410000000000014716761556020064 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/spec/nulldb_spec.rb0000644000004100000410000004112714716761556022710 0ustar www-datawww-datarequire 'rubygems' # Optional simplecov loading begin require 'simplecov' SimpleCov.start rescue LoadError end require 'active_record' require 'active_record/version' $: << File.join(File.dirname(__FILE__), "..", "lib") require 'rspec' require 'nulldb_rspec' class Employee < ActiveRecord::Base after_save :on_save_finished def on_save_finished end end class TablelessModel < ActiveRecord::Base end NullDB.configure {|ndb| ndb.project_root = 'Rails.root'} describe "NullDB with no schema pre-loaded" do before :each do allow( Kernel ).to receive :load allow( ActiveRecord::Migration ).to receive :verbose= end it "should load Rails.root/db/schema.rb if no alternate is specified" do ActiveRecord::Base.establish_connection :adapter => :nulldb expect( Kernel ).to receive(:load).with("Rails.root/db/schema.rb") ActiveRecord::Base.connection.columns('schema_info') end it "should load the specified schema relative to Rails.root" do expect( Kernel ).to receive(:load).with("Rails.root/foo/myschema.rb") ActiveRecord::Base.establish_connection :adapter => :nulldb, :schema => "foo/myschema.rb" ActiveRecord::Base.connection.columns('schema_info') end it "should suppress migration output" do expect( ActiveRecord::Migration).to receive(:verbose=).with(false) ActiveRecord::Base.establish_connection :adapter => :nulldb, :schema => "foo/myschema.rb" ActiveRecord::Base.connection.columns('schema_info') end it "should allow creating a table without passing a block" do ActiveRecord::Base.establish_connection :adapter => :nulldb ActiveRecord::Schema.define do create_table(:employees) end end end describe "NullDB" do before :all do ActiveRecord::Base.establish_connection :adapter => :nulldb ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table(:employees) do |t| t.string :name, null: false, limit: 50 t.date :hire_date t.integer :employee_number t.decimal :salary t.boolean :active, default: true end create_table(:employees_widgets, :id => false, :force => true) do |t| t.integer :employee_id t.integer :widget_id end add_index "employees", :name, :name => "index_employees_on_name" add_index "employees", ["employee_number"], :name => "index_employees_on_employee_number", :unique => true add_index "employees", :hire_date remove_index "employees", :hire_date add_index "employees_widgets", ["employee_id", "widget_id"], :name => "my_index" add_fk_constraint "foo", "bar", "baz", "buz", "bungle" add_pk_constraint "foo", "bar", {}, "baz", "buz" end end before :each do @employee = Employee.new(:name => "John Smith", :hire_date => Date.civil(2000, 1, 1), :employee_number => 42, :salary => 56000.00) end it "should set the @config instance variable so plugins that assume its there can use it" do expect( Employee.connection.instance_variable_get(:@config)[:adapter]).to eq :nulldb end it "should enable instantiation of AR objects without a database" do expect( @employee ).to be_a_kind_of(ActiveRecord::Base) end it "should remember columns defined in migrations" do should_have_column(Employee, :name, :string) should_have_column(Employee, :hire_date, :date) should_have_column(Employee, :employee_number, :integer) should_have_column(Employee, :salary, :decimal) should_have_column(Employee, :active, :boolean) end it 'should have limit on name' do expect(Employee.columns_hash['name'].limit).to eq 50 end it "should return true on nullable field" do expect(Employee.columns_hash['salary'].null).to be true end it "should return false on non-nullable field" do expect(Employee.columns_hash['name'].null).to be false end it "should stringify default values" do expect(Employee.columns_hash['active'].default).to eq "true" end it "should have no default for employee_number" do expect(Employee.columns_hash['employee_number'].default).to eq nil end it "should return the appropriate primary key" do expect( ActiveRecord::Base.connection.primary_key('employees') ).to eq 'id' end it "should return a nil primary key on habtm" do expect( ActiveRecord::Base.connection.primary_key('employees_widgets') ).to eq nil end it "should return an empty array of columns for a table-less model" do expect( TablelessModel.columns).to eq [] end it "should enable simulated saving of AR objects" do expect{ @employee.save! }.to_not raise_error end it "should enable AR callbacks during simulated save" do expect( @employee ).to receive :on_save_finished @employee.save end it "should enable simulated deletes of AR objects" do expect{ @employee.destroy }.to_not raise_error end it "should enable simulated creates of AR objects" do emp = Employee.create(:name => "Bob Jones") expect( emp.name ).to eq "Bob Jones" end it "should generate new IDs when inserting unsaved objects" do cxn = Employee.connection id1 = cxn.insert("some sql", "SomeClass Create", "id", nil, nil) id2 = cxn.insert("some sql", "SomeClass Create", "id", nil, nil) expect( id2 ).to eq (id1 + 1) end it "should re-use object ID when inserting saved objects" do cxn = Employee.connection id1 = cxn.insert("some sql", "SomeClass Create", "id", 23, nil) expect( id1 ).to eq 23 end it "should log executed SQL statements" do cxn = Employee.connection exec_count = cxn.execution_log.size @employee.save! expect( cxn.execution_log.size ).to eq (exec_count + 1) end it "should have the adapter name 'NullDB'" do expect( Employee.connection.adapter_name ).to eq "NullDB" end it "should support migrations" do expect( Employee.connection.supports_migrations? ).to eq true end it "should always have a schema_info table definition" do expect( Employee.connection.tables ).to include "schema_info" end it "should return an empty array from #select" do result = Employee.connection.select_all("who cares", "blah") expect( result ).to eq [] end it "should provide a way to set log checkpoints" do cxn = Employee.connection @employee.save! expect( cxn.execution_log_since_checkpoint.size ).to be > 0 cxn.checkpoint! expect( cxn.execution_log_since_checkpoint.size ).to eq 0 @employee.salary = @employee.salary + 1 @employee.save! expect( cxn.execution_log_since_checkpoint.size ).to eq 1 end def should_contain_statement(cxn, entry_point) expect( cxn.execution_log_since_checkpoint).to \ include(ActiveRecord::ConnectionAdapters::NullDBAdapter::Statement.new(entry_point)) end def should_not_contain_statement(cxn, entry_point) expect( cxn.execution_log_since_checkpoint ).to_not \ include(ActiveRecord::ConnectionAdapters::NullDBAdapter::Statement.new(entry_point)) end it "should tag logged statements with their entry point" do cxn = Employee.connection should_not_contain_statement(cxn, :insert) @employee.save should_contain_statement(cxn, :insert) cxn.checkpoint! should_not_contain_statement(cxn, :update) @employee.salary = @employee.salary + 1 @employee.save should_contain_statement(cxn, :update) cxn.checkpoint! should_not_contain_statement(cxn, :delete) @employee.destroy should_contain_statement(cxn, :delete) cxn.checkpoint! should_not_contain_statement(cxn, :select_all) Employee.all.each do |emp|; end should_contain_statement(cxn, :select_all) cxn.checkpoint! should_not_contain_statement(cxn, :select_value) Employee.count_by_sql("frobozz") should_contain_statement(cxn, :select_value) cxn.checkpoint! should_not_contain_statement(cxn, :select_values) cxn.select_values("") should_contain_statement(cxn, :select_values) end it "should allow #finish to be called on the result of #execute" do Employee.connection.execute("blah").finish end it "should #to_a return empty array on the result of #execute" do result = Employee.connection.execute("blah") expect( result.to_a ).to be_a Array expect( result.to_a ).to be_empty end def should_have_column(klass, col_name, col_type) col = klass.columns_hash[col_name.to_s] expect(col.sql_type.to_s.gsub(/\([0-9]+\)/, "").to_sym).to eq col_type end it "should support adding and removing indexes" do expect( Employee.connection.indexes('employees').size ).to eq 2 expect( Employee.connection.indexes('employees_widgets').size ).to eq 1 end it "should support unique indexes" do expect( Employee.connection.indexes('employees').detect{|idx| idx.columns == ["name"]}.unique ).to eq false expect( Employee.connection.indexes('employees').detect{|idx| idx.columns == ["employee_number"]}.unique ).to eq true end it "should support multi-column indexes" do expect( Employee.connection.indexes('employees_widgets').first.columns).to eq ["employee_id", "widget_id"] end it "should support custom index names" do expect( Employee.connection.indexes('employees_widgets').first.name ).to eq 'my_index' end it 'should handle ActiveRecord::ConnectionNotEstablished' do expect( ActiveRecord::Base ).to receive(:connection_pool).and_raise(ActiveRecord::ConnectionNotEstablished) expect { NullDB.nullify }.to_not raise_error end it 'should handle count queries' do expect(Employee.count).to eql(0) end end # need a fallback db for contextual nullification if defined?(ActiveRecord::DatabaseConfigurations) db_config = { 'test' => {'adapter' => 'nulldb'} } ActiveRecord::Base.configurations = ActiveRecord::DatabaseConfigurations.new(db_config) else # Support ActiveRecord 5 ActiveRecord::Base.configurations['test'] = {'adapter' => 'nulldb'} end describe NullDB::RSpec::NullifiedDatabase do describe 'have_executed rspec matcher' do before(:all) do ActiveRecord::Schema.define do create_table(:employees) end end include NullDB::RSpec::NullifiedDatabase before { NullDB.checkpoint } it 'passes if an execution was made' do expect( Employee.connection ).to receive(:insert) allow( Kernel ).to receive :load Employee.create end end describe '.globally_nullify_database' do it 'nullifies the database' do expect( NullDB::RSpec::NullifiedDatabase ).to respond_to(:nullify_database) expect( NullDB::RSpec::NullifiedDatabase ).to receive(:nullify_database) NullDB::RSpec::NullifiedDatabase.globally_nullify_database end end end describe 'table changes' do before(:each) do ActiveRecord::Base.establish_connection :adapter => :nulldb ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table(:employees) do |t| t.string :name, null: false, limit: 50 t.date :hire_date t.integer :employee_number t.decimal :salary end end end def should_have_column(klass, col_name, col_type) col = klass.columns_hash[col_name.to_s] expect(col.sql_type.to_s.gsub(/\([0-9]+\)/, "").to_sym).to eq col_type end describe 'rename_table' do it 'should rename a table' do expect{ ActiveRecord::Schema.define do rename_table :employees, :workers end }.to_not raise_error class Worker < ActiveRecord::Base after_save :on_save_finished def on_save_finished end end should_have_column(Worker, :name, :string) should_have_column(Worker, :hire_date, :date) should_have_column(Worker, :employee_number, :integer) should_have_column(Worker, :salary, :decimal) worker = Worker.create(:name => "Bob Jones") expect(worker.name).to eq "Bob Jones" end end describe 'add_column' do it 'should add a column to an existing table' do expect{ ActiveRecord::Schema.define do add_column :employees, :title, :string end Employee.connection.schema_cache.clear! Employee.reset_column_information }.to_not raise_error should_have_column(Employee, :name, :string) should_have_column(Employee, :hire_date, :date) should_have_column(Employee, :employee_number, :integer) should_have_column(Employee, :salary, :decimal) should_have_column(Employee, :title, :string) end end describe 'change_column' do it 'should change the column type' do expect{ ActiveRecord::Schema.define do change_column :employees, :name, :text end Employee.connection.schema_cache.clear! Employee.reset_column_information }.to_not raise_error should_have_column(Employee, :name, :text) should_have_column(Employee, :hire_date, :date) should_have_column(Employee, :employee_number, :integer) should_have_column(Employee, :salary, :decimal) end end describe 'rename_column' do it 'should rename a column' do expect{ ActiveRecord::Schema.define do rename_column :employees, :name, :full_name end Employee.connection.schema_cache.clear! Employee.reset_column_information }.to_not raise_error should_have_column(Employee, :full_name, :string) should_have_column(Employee, :hire_date, :date) should_have_column(Employee, :employee_number, :integer) should_have_column(Employee, :salary, :decimal) end end describe 'change_column_default' do it 'should change default value of a column' do expect{ ActiveRecord::Schema.define do change_column_default :employees, :name, 'Jon Doe' end Employee.connection.schema_cache.clear! Employee.reset_column_information }.to_not raise_error columns = Employee.columns expect(columns.second.default).to eq('Jon Doe') end it 'should change default value of a with has syntax' do expect{ ActiveRecord::Schema.define do change_column_default :employees, :name, from: nil, to: 'Jon Doe' end Employee.connection.schema_cache.clear! Employee.reset_column_information }.to_not raise_error columns = Employee.columns expect(columns.second.default).to eq('Jon Doe') end end end describe 'adapter-specific extensions' do before(:all) do ActiveRecord::Base.establish_connection :adapter => :nulldb ActiveRecord::Migration.verbose = false end def should_have_column(klass, col_name, col_type) col = klass.columns_hash[col_name.to_s] expect(col.sql_type.to_s.gsub(/\([0-9]+\)/, "").to_sym).to eq col_type end it "supports 'enable_extension' in the schema definition" do expect{ ActiveRecord::Schema.define do enable_extension "plpgsql" end }.to_not raise_error end it 'supports postgres extension columns' do expect { ActiveRecord::Schema.define do create_table :extended_models do |t| t.citext :text t.interval :time_interval t.geometry :feature_geometry, srid: 4326, type: "multi_polygon" t.jsonb :jsonb_column t.hstore :hstore_column end end }.to_not raise_error class ExtendedModel < ActiveRecord::Base end should_have_column(ExtendedModel, :text, :text) should_have_column(ExtendedModel, :time_interval, :text) should_have_column(ExtendedModel, :feature_geometry, :text) should_have_column(ExtendedModel, :jsonb_column, :json) end it 'supports ActiveModel attributes with postgres modifiers' do class ExtendedModel < ActiveRecord::Base attribute :strings, :string, array: true attribute :size, :integer, range: true end expect(ExtendedModel.type_for_attribute(:strings)) .to be_a ActiveRecord::ConnectionAdapters::NullDBAdapter::DummyOID expect(ExtendedModel.new(strings: %w[a b]).strings).to eq %w[a b] expect(ExtendedModel.type_for_attribute(:size)) .to be_a ActiveRecord::ConnectionAdapters::NullDBAdapter::DummyOID expect(ExtendedModel.new(size: 1..5).size).to eq 1..5 end it 'registers a primary_key type' do expect(ActiveRecord::Type.lookup(:primary_key, adapter: 'NullDB')) .to be_a(ActiveModel::Type::Integer) end end describe ActiveRecord::ConnectionAdapters::NullDBAdapter::EmptyResult do it "should return an empty array from #cast_values" do result = described_class.new expect( result.cast_values ).to be_a Array expect( result.cast_values ).to be_empty end end activerecord-nulldb-adapter-1.1.1/spec/spec.opts0000644000004100000410000000001714716761556021723 0ustar www-datawww-data--format nestedactiverecord-nulldb-adapter-1.1.1/activerecord-nulldb-adapter.gemspec0000644000004100000410000000227014716761556026046 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'nulldb/version' Gem::Specification.new do |s| s.name = "activerecord-nulldb-adapter" s.version = NullDB::VERSION s.require_paths = ["lib"] s.authors = ["Avdi Grimm", "Myron Marston", "Danilo Cabello"] s.summary = "The Null Object pattern as applied to ActiveRecord database adapters" s.description = "A database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including after_save hooks - without ever touching a real database." s.email = "cabello@users.noreply.github.com" s.extra_rdoc_files = [ "LICENSE", "README.md" ] s.files = `git ls-files`.split($/) s.homepage = "https://github.com/nulldb/nulldb" s.licenses = ["MIT"] s.add_runtime_dependency 'activerecord', '>= 6.0', '< 8.1' s.add_development_dependency 'spec' s.add_development_dependency 'rdoc' s.add_development_dependency 'rspec' s.add_development_dependency 'rake' s.add_development_dependency 'appraisal' s.add_development_dependency 'simplecov' s.add_development_dependency 'pry-byebug' end activerecord-nulldb-adapter-1.1.1/gemfiles/0000755000004100000410000000000014716761556020725 5ustar www-datawww-dataactiverecord-nulldb-adapter-1.1.1/gemfiles/activerecord_7.0.gemfile0000644000004100000410000000043014716761556025312 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", "~> 7.0.0" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_6.1.gemfile0000644000004100000410000000043014716761556025312 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", "~> 6.1.0" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_master.gemfile0000644000004100000410000000046214716761556026306 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", github: "rails/rails", branch: :main group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_7.2.gemfile0000644000004100000410000000043014716761556025314 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", "~> 7.2.0" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_6.0.gemfile0000644000004100000410000000043014716761556025311 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", "~> 6.0.0" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_7.1.gemfile0000644000004100000410000000043014716761556025313 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", "~> 7.1.0" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/gemfiles/activerecord_8.0.gemfile0000644000004100000410000000047114716761556025320 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "activerecord", github: "rails/rails", branch: "8-0-stable" group :development, :test do gem "spec" gem "rspec", ">= 1.2.9" gem "rake" gem "rdoc" end group :development do gem "appraisal" gem "simplecov", require: false end activerecord-nulldb-adapter-1.1.1/Rakefile0000644000004100000410000000044214716761556020577 0ustar www-datawww-datarequire 'rubygems' require 'rake' require 'rspec/core/rake_task' require 'bundler/gem_tasks' RSpec::Core::RakeTask.new(:spec) task :default => :spec require 'rdoc/task' Rake::RDocTask.new do |rd| rd.main = "README.md" rd.rdoc_files.include("README.md", "LICENSE", "lib/**/*.rb") end activerecord-nulldb-adapter-1.1.1/Gemfile0000644000004100000410000000037214716761556020427 0ustar www-datawww-datasource "https://rubygems.org" gem 'activerecord', '>= 6.0', '< 8.1' group :development, :test do gem 'spec' gem 'rspec', '>= 1.2.9' gem 'rake' gem 'rdoc' end group :development do gem 'appraisal' gem 'simplecov', :require => false end activerecord-nulldb-adapter-1.1.1/LICENSE0000644000004100000410000000205714716761556020143 0ustar www-datawww-dataThe MIT License Copyright (c) 2008 Avdi Grimm Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. activerecord-nulldb-adapter-1.1.1/README.md0000644000004100000410000001233314716761556020413 0ustar www-datawww-data[Gem
Version](http://badge.fury.io/rb/activerecord-nulldb-adapter) [](https://codeclimate.com/github/nulldb/nulldb) [Build Status](https://github.com/nulldb/nulldb/actions) # The NullDB Connection Adapter Plugin ## What NullDB is the Null Object pattern as applied to ActiveRecord database adapters. It is a database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including `after_save` hooks - without ever touching a real database. ## Compatibility ### Ruby Currently supported Ruby versions: `2.7.X`, `3.X`. Experimental support provided for: JRuby ### ActiveRecord Any version of ActiveRecord `>= 6.1` ## Installation ```bash gem install activerecord-nulldb-adapter ``` ## How Once installed, NullDB can be used much like any other ActiveRecord database adapter: ```ruby ActiveRecord::Base.establish_connection :adapter => :nulldb ``` NullDB needs to know where you keep your schema file in order to reflect table metadata. By default it looks in RAILS_ROOT/db/schema.rb. You can override that by setting the `schema` option: ```ruby ActiveRecord::Base.establish_connection :adapter => :nulldb, :schema => 'foo/myschema.rb' ``` NullDB comes with RSpec integration. To replace the database with NullDB in all of your specs, put the following in your spec/rails_helper: ```ruby require 'nulldb_rspec' include NullDB::RSpec::NullifiedDatabase ``` after you load your rails environment ```ruby require File.expand_path('../config/environment', __dir__) ``` otherwise you will encounter issues such as ([bug)](https://github.com/nulldb/nulldb/pull/90#issuecomment-496690958). Or if you just want to use NullDB in a specific spec context, you can include the same module inside a context: ```ruby require 'nulldb_rspec' describe Employee, "with access to the database" do fixtures :employees # ... end describe Employee, "with NullDB" do include NullDB::RSpec::NullifiedDatabase # ... end ``` If you want to have NullDB enabled by default but disabled for particular contexts then (see this [post)](https://web.archive.org/web/20120419204019/http://andywaite.com/2011/5 /18/rspec-disable-nulldb) NullDB::Rspec provides some custom matcher support for verifying expectations about interactions with the database: ```ruby describe Employee do include NullDB::RSpec::NullifiedDatabase it "should cause an insert statement to be executed" do Employee.create! Employee.connection.should have_executed(:insert) end end ``` UnitRecord-style verification that no database calls have been made at all can be achieved by using the special `:anything` symbol: ```ruby describe "stuff that shouldn't touch the database" do after :each do Employee.connection.should_not have_executed(:anything) end # ... end ``` You can also experiment with putting NullDB in your database.yml: ```yaml unit_test: adapter: nulldb ``` However, due to the way Rails hard-codes specific database adapters into its standard Rake tasks, you may find that this generates unexpected and difficult-to-debug behavior. Workarounds for this are under development. ## Why There are a number of advantages to writing unit tests that never touch the database. The biggest is probably speed of execution - unit tests must be fast for test-driven development to be practical. Another is separation of concerns: unit tests should be exercising only the business logic contained in your models, not ActiveRecord. For more on why testing-sans-database is a good idea, see: http://www.dcmanges.com/blog/rails-unit-record-test-without-the-database. NullDB is one way to separate your unit tests from the database. It was inspired by the [ARBS](http://arbs.rubyforge.org/) and [UnitRecord](http://unit-test-ar.rubyforge.org/) libraries. It differs from them in that rather than modifying parts of ActiveRecord, it implements the same [semi-]well-documented public interface that the other standard database adapters, like MySQL and SQLServer, implement. This has enabled it to evolve to support new ActiveRecord versions relatively easily. One concrete advantage of this null-object pattern design is that it is possible with NullDB to test `after_save` hooks. With NullDB, you can call `#save` and all of the usual callbacks will be called - but nothing will be saved. ## Limitations * It is **not** an in-memory database. Finds will not work. Neither will `reload`, currently. Test fixtures won't work either, for obvious reasons. * It has only the most rudimentery schema/migration support. Complex migrations will probably break it. * Lots of other things probably don't work. Patches welcome! ## Who NullDB was originally written by Avdi Grimm . It is currently maintained by [Danilo Cabello](https://github.com/cabello). Previously maintained by: [Bram de Vries](https://github.com/blaet). ## Where * Homepage: https://github.com/nulldb/nulldb ## License See the LICENSE file for licensing information.