diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7f61f51..d50ff2a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,9 +14,7 @@ jobs: fail-fast: false matrix: include: - - ruby: "2.7.8" - gemfile: Gemfile.6.1.sqlite3 - - ruby: "3.0.7" + - ruby: "3.1.6" gemfile: Gemfile.7.1.sqlite3 - ruby: "3.1.6" gemfile: Gemfile.7.2.sqlite3 @@ -24,6 +22,8 @@ jobs: gemfile: Gemfile.7.2.sqlite3 - ruby: "3.3.6" gemfile: Gemfile.8.0.sqlite3 + - ruby: "3.4.7" + gemfile: Gemfile.8.1.sqlite3 env: BUNDLE_GEMFILE: ${{ matrix.gemfile }} @@ -96,12 +96,10 @@ jobs: fail-fast: false matrix: include: - - ruby: "3.0.7" - gemfile: Gemfile.6.1.pg - - ruby: "3.2.6" - gemfile: Gemfile.7.1.pg - ruby: "3.2.6" gemfile: Gemfile.7.2.pg + - ruby: "3.4.7" + gemfile: Gemfile.8.1.pg env: BUNDLE_GEMFILE: ${{ matrix.gemfile }} diff --git a/.ruby-version b/.ruby-version index a3ec5a4..2f4b607 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2 +3.4 diff --git a/CHANGELOG.md b/CHANGELOG.md index c530ea0..91842e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## 2.7.0 (2025-11-03) +* Removed: Support for Ruby < 3.1, Rails < 7. +* Fixed: Exception when using ActiveType::Record with Rails 8.1. + ## 2.6.5 (2025-10-16) * Fixed: ActiveType::Object and ActiveType::Record are now serialized/deserialized correctly using Marshal.dump/Marshal.load diff --git a/Gemfile.6.1.pg.lock b/Gemfile.6.1.pg.lock deleted file mode 100644 index d7e471b..0000000 --- a/Gemfile.6.1.pg.lock +++ /dev/null @@ -1,59 +0,0 @@ -PATH - remote: . - specs: - active_type (2.6.5) - activerecord (>= 6.1) - -GEM - remote: https://rubygems.org/ - specs: - activemodel (6.1.3) - activesupport (= 6.1.3) - activerecord (6.1.3) - activemodel (= 6.1.3) - activesupport (= 6.1.3) - activesupport (6.1.3) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - concurrent-ruby (1.1.8) - diff-lcs (1.4.4) - gemika (0.6.0) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - minitest (5.14.4) - pg (1.2.3) - rake (13.0.3) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-support (3.10.2) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - zeitwerk (2.4.2) - -PLATFORMS - ruby - x86_64-linux - -DEPENDENCIES - active_type! - activerecord (~> 6.1.0) - gemika - pg - rake - rspec (~> 3.4) - -BUNDLED WITH - 2.2.27 diff --git a/Gemfile.6.1.sqlite3.lock b/Gemfile.6.1.sqlite3.lock deleted file mode 100644 index 96aa7a2..0000000 --- a/Gemfile.6.1.sqlite3.lock +++ /dev/null @@ -1,59 +0,0 @@ -PATH - remote: . - specs: - active_type (2.6.5) - activerecord (>= 6.1) - -GEM - remote: https://rubygems.org/ - specs: - activemodel (6.1.3) - activesupport (= 6.1.3) - activerecord (6.1.3) - activemodel (= 6.1.3) - activesupport (= 6.1.3) - activesupport (6.1.3) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - concurrent-ruby (1.1.8) - diff-lcs (1.4.4) - gemika (0.6.0) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - minitest (5.14.4) - rake (13.0.3) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-support (3.10.2) - sqlite3 (1.4.2) - tzinfo (2.0.4) - concurrent-ruby (~> 1.0) - zeitwerk (2.4.2) - -PLATFORMS - ruby - x86_64-linux - -DEPENDENCIES - active_type! - activerecord (~> 6.1.0) - gemika - rake - rspec (~> 3.4) - sqlite3 - -BUNDLED WITH - 2.2.27 diff --git a/Gemfile.7.1.pg b/Gemfile.7.1.pg deleted file mode 100644 index 0f95fbc..0000000 --- a/Gemfile.7.1.pg +++ /dev/null @@ -1,9 +0,0 @@ -source 'https://rubygems.org' - -gem 'activerecord', '~>7.1.0' -gem 'rspec', '~>3.4' -gem 'pg' -gem 'rake' -gem 'gemika' - -gem 'active_type', :path => '.' diff --git a/Gemfile.7.1.pg.lock b/Gemfile.7.1.pg.lock deleted file mode 100644 index 589bb5a..0000000 --- a/Gemfile.7.1.pg.lock +++ /dev/null @@ -1,68 +0,0 @@ -PATH - remote: . - specs: - active_type (2.6.5) - activerecord (>= 6.1) - -GEM - remote: https://rubygems.org/ - specs: - activemodel (7.1.3.4) - activesupport (= 7.1.3.4) - activerecord (7.1.3.4) - activemodel (= 7.1.3.4) - activesupport (= 7.1.3.4) - timeout (>= 0.4.0) - activesupport (7.1.3.4) - base64 - bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) - base64 (0.2.0) - bigdecimal (3.1.8) - concurrent-ruby (1.3.4) - connection_pool (2.4.1) - diff-lcs (1.5.1) - drb (2.2.1) - gemika (0.8.3) - i18n (1.14.5) - concurrent-ruby (~> 1.0) - minitest (5.24.1) - mutex_m (0.2.0) - pg (1.5.7) - rake (13.2.1) - rspec (3.13.0) - rspec-core (~> 3.13.0) - rspec-expectations (~> 3.13.0) - rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) - rspec-support (~> 3.13.0) - rspec-expectations (3.13.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-mocks (3.13.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.13.0) - rspec-support (3.13.1) - timeout (0.4.1) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - -PLATFORMS - ruby - -DEPENDENCIES - active_type! - activerecord (~> 7.1.0) - gemika - pg - rake - rspec (~> 3.4) - -BUNDLED WITH - 2.5.6 diff --git a/Gemfile.7.1.sqlite3.lock b/Gemfile.7.1.sqlite3.lock index e044365..fa94a4f 100644 --- a/Gemfile.7.1.sqlite3.lock +++ b/Gemfile.7.1.sqlite3.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_type (2.6.5) + active_type (2.7.0) activerecord (>= 6.1) GEM diff --git a/Gemfile.7.2.mysql2.lock b/Gemfile.7.2.mysql2.lock index 063cc19..54d46b4 100644 --- a/Gemfile.7.2.mysql2.lock +++ b/Gemfile.7.2.mysql2.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_type (2.6.5) + active_type (2.7.0) activerecord (>= 6.1) GEM diff --git a/Gemfile.7.2.pg.lock b/Gemfile.7.2.pg.lock index afe7092..d11a9ab 100644 --- a/Gemfile.7.2.pg.lock +++ b/Gemfile.7.2.pg.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_type (2.6.5) + active_type (2.7.0) activerecord (>= 6.1) GEM diff --git a/Gemfile.7.2.sqlite3.lock b/Gemfile.7.2.sqlite3.lock index 3458c0f..4c4409c 100644 --- a/Gemfile.7.2.sqlite3.lock +++ b/Gemfile.7.2.sqlite3.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_type (2.6.5) + active_type (2.7.0) activerecord (>= 6.1) GEM diff --git a/Gemfile.8.0.sqlite3.lock b/Gemfile.8.0.sqlite3.lock index fadc960..b241f49 100644 --- a/Gemfile.8.0.sqlite3.lock +++ b/Gemfile.8.0.sqlite3.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_type (2.6.5) + active_type (2.7.0) activerecord (>= 6.1) GEM diff --git a/Gemfile.6.1.pg b/Gemfile.8.1.pg similarity index 79% rename from Gemfile.6.1.pg rename to Gemfile.8.1.pg index 4242000..dfe4481 100644 --- a/Gemfile.6.1.pg +++ b/Gemfile.8.1.pg @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'activerecord', '~>6.1.0' +gem 'activerecord', '~>8.1.0' gem 'rspec', '~>3.4' gem 'pg' gem 'rake' diff --git a/Gemfile.8.1.pg.lock b/Gemfile.8.1.pg.lock new file mode 100644 index 0000000..54ea964 --- /dev/null +++ b/Gemfile.8.1.pg.lock @@ -0,0 +1,86 @@ +PATH + remote: . + specs: + active_type (2.7.0) + activerecord (>= 6.1) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (8.1.0) + activesupport (= 8.1.0) + activerecord (8.1.0) + activemodel (= 8.1.0) + activesupport (= 8.1.0) + timeout (>= 0.4.0) + activesupport (8.1.0) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + base64 (0.3.0) + bigdecimal (3.3.1) + concurrent-ruby (1.3.5) + connection_pool (2.5.4) + diff-lcs (1.6.2) + drb (2.2.3) + gemika (1.0.0) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + json (2.15.1) + logger (1.7.0) + minitest (5.26.0) + pg (1.6.2) + pg (1.6.2-aarch64-linux) + pg (1.6.2-aarch64-linux-musl) + pg (1.6.2-arm64-darwin) + pg (1.6.2-x86_64-darwin) + pg (1.6.2-x86_64-linux) + pg (1.6.2-x86_64-linux-musl) + rake (13.3.0) + rspec (3.13.2) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.6) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.6) + securerandom (0.4.1) + timeout (0.4.3) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.0.4) + +PLATFORMS + aarch64-linux + aarch64-linux-musl + arm64-darwin + ruby + x86_64-darwin + x86_64-linux + x86_64-linux-musl + +DEPENDENCIES + active_type! + activerecord (~> 8.1.0) + gemika + pg + rake + rspec (~> 3.4) + +BUNDLED WITH + 2.6.9 diff --git a/Gemfile.6.1.sqlite3 b/Gemfile.8.1.sqlite3 similarity index 80% rename from Gemfile.6.1.sqlite3 rename to Gemfile.8.1.sqlite3 index b614965..30fd43f 100644 --- a/Gemfile.6.1.sqlite3 +++ b/Gemfile.8.1.sqlite3 @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'activerecord', '~>6.1.0' +gem 'activerecord', '~>8.1.0' gem 'rspec', '~>3.4' gem 'sqlite3' gem 'rake' diff --git a/Gemfile.8.1.sqlite3.lock b/Gemfile.8.1.sqlite3.lock new file mode 100644 index 0000000..b50b5db --- /dev/null +++ b/Gemfile.8.1.sqlite3.lock @@ -0,0 +1,92 @@ +PATH + remote: . + specs: + active_type (2.7.0) + activerecord (>= 6.1) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (8.1.0) + activesupport (= 8.1.0) + activerecord (8.1.0) + activemodel (= 8.1.0) + activesupport (= 8.1.0) + timeout (>= 0.4.0) + activesupport (8.1.0) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + base64 (0.3.0) + bigdecimal (3.3.1) + concurrent-ruby (1.3.5) + connection_pool (2.5.4) + diff-lcs (1.6.2) + drb (2.2.3) + gemika (1.0.0) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + json (2.15.1) + logger (1.7.0) + minitest (5.26.0) + rake (13.3.0) + rspec (3.13.2) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.6) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-support (3.13.6) + securerandom (0.4.1) + sqlite3 (2.7.4-aarch64-linux-gnu) + sqlite3 (2.7.4-aarch64-linux-musl) + sqlite3 (2.7.4-arm-linux-gnu) + sqlite3 (2.7.4-arm-linux-musl) + sqlite3 (2.7.4-arm64-darwin) + sqlite3 (2.7.4-x86-linux-gnu) + sqlite3 (2.7.4-x86-linux-musl) + sqlite3 (2.7.4-x86_64-darwin) + sqlite3 (2.7.4-x86_64-linux-gnu) + sqlite3 (2.7.4-x86_64-linux-musl) + timeout (0.4.3) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.0.4) + +PLATFORMS + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + active_type! + activerecord (~> 8.1.0) + gemika + rake + rspec (~> 3.4) + sqlite3 + +BUNDLED WITH + 2.5.6 diff --git a/README.md b/README.md index 40ec3c7..c2f0c8d 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ Supported options for `nests_many` / `nests_one` are: nests_many :documents, build_scope: proc { Document }, find_scope: proc { Document } ``` - All `...scope` options are evaled in the context of the record on first use, and cached. + All `...scope` options are evaled in the context of the record on first use, and cached. - `allow_destroy` @@ -380,7 +380,7 @@ sign_up.is_a?(SignUp) # => true This is basically like [`ActiveRecord#becomes`](http://apidock.com/rails/v4.2.1/ActiveRecord/Persistence/becomes), but with less bugs and more consistent behavior. **Note that `cast` is destructive.** The originally casted record (`user`) and the returned record (`sign_up`) -share internal state (such as attributes). To avoid unexpected behavior, the original record will raise an error when trying to change or persist it. Also, casting of a record that has changes in its loaded associations is prevented, because those changes would be lost. +share internal state (such as attributes). To avoid unexpected behavior, the original record will raise an error when trying to change or persist it. Also, casting of a record that has changes in its loaded associations is prevented, because those changes would be lost. If you know what you are doing and absolutely want that, you may use the option `force: true` to allow this potentially problematic behaviour, e.g. `sign_up = ActiveType.cast(user, SignUp, force: true)` @@ -434,14 +434,14 @@ Now, if you load `credentials`, you will automatically receive records of type ` Supported Rails versions ------------------------ -ActiveType is tested against ActiveRecord 6.1, 7.1, 7.2, 8.0. +ActiveType is tested against ActiveRecord 7.1, 7.2, 8.0, 8.1. Later versions might work, earlier will not. Supported Ruby versions ------------------------ -ActiveType is tested against Ruby 2.7+. +ActiveType is tested against Ruby 3.1+. Installation @@ -478,5 +478,3 @@ Credits Tobias Kraze from [makandra](http://makandra.com/) Henning Koch from [makandra](http://makandra.com/) - - diff --git a/lib/active_type.rb b/lib/active_type.rb index 4a20023..c2e4d66 100644 --- a/lib/active_type.rb +++ b/lib/active_type.rb @@ -4,13 +4,6 @@ require 'active_record' -if ActiveRecord::VERSION::STRING == '4.2.0' - raise(<<-MESSAGE.strip_heredoc) - ActiveType is not compatible with ActiveRecord 4.2.0. Please upgrade to 4.2.1 - For details see https://github.com/makandra/active_type/issues/31 - MESSAGE -end - module ActiveType extend ActiveSupport::Autoload diff --git a/lib/active_type/change_association.rb b/lib/active_type/change_association.rb index 7ddeb25..18788fa 100644 --- a/lib/active_type/change_association.rb +++ b/lib/active_type/change_association.rb @@ -13,12 +13,8 @@ def change_association(association_name, new_scope, new_options = {}) new_scope = nil end original_options = existing_association.options - if ActiveRecord::VERSION::MAJOR > 3 - new_scope ||= existing_association.scope - public_send(existing_association.macro, association_name, new_scope, **original_options.merge(new_options)) - else - public_send(existing_association.macro, association_name, **original_options.merge(new_options)) - end + new_scope ||= existing_association.scope + public_send(existing_association.macro, association_name, new_scope, **original_options.merge(new_options)) else raise ArgumentError, "unrecognized association `#{association_name}`" end diff --git a/lib/active_type/nested_attributes/association.rb b/lib/active_type/nested_attributes/association.rb index cf7727d..0eb3497 100644 --- a/lib/active_type/nested_attributes/association.rb +++ b/lib/active_type/nested_attributes/association.rb @@ -17,14 +17,7 @@ def initialize(owner, target_name, options = {}) @reject_if = options.delete(:reject_if) @options = options.dup - @index_errors = case - when ActiveRecord::VERSION::MAJOR < 5 - @options[:index_errors] - when ActiveRecord::VERSION::MAJOR < 7 - @options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors - else - @options[:index_errors] || ActiveRecord.index_nested_attribute_errors - end + @index_errors = @options[:index_errors] || ActiveRecord.index_nested_attribute_errors end def assign_attributes(parent, attributes) @@ -130,17 +123,9 @@ def valid_options end def add_errors_to_parent(parent, child, index) - if Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new("6.1") - child.errors.each do |error| - attribute = translate_error_attribute(error.attribute, index) - parent.errors.add(attribute, error.message) - end - else - child.errors.each do |attribute, message| - attribute = translate_error_attribute(attribute, index) - parent.errors.add(attribute, message) - parent.errors[attribute].uniq! - end + child.errors.each do |error| + attribute = translate_error_attribute(error.attribute, index) + parent.errors.add(attribute, error.message) end end diff --git a/lib/active_type/no_table.rb b/lib/active_type/no_table.rb index 3ffb33b..f1f1573 100644 --- a/lib/active_type/no_table.rb +++ b/lib/active_type/no_table.rb @@ -1,201 +1,115 @@ module ActiveType + module NoTable - if ActiveRecord::VERSION::MAJOR < 5 + extend ActiveSupport::Concern - module NoTable - - extend ActiveSupport::Concern - - module ClassMethods - - def column_types - {} - end - - def columns - [] - end - - def primary_key - nil - end - - def destroy(*) - new - end - - def destroy_all(*) - [] - end - - def find_by_sql(*) - [] - end + class DummySchemaCache + def columns_hash(table_name) + {} end - def id - nil + def columns_hash?(table_name) + return false end - def attribute_names - [] + def data_source_exists?(table_name) + false end - def transaction(&block) - @_current_transaction_records ||= [] - yield + def clear_data_source_cache!(table_name) end - def destroy - @destroyed = true - freeze - end + end - def reload - self + class DummyPool < ActiveRecord::ConnectionAdapters::NullPool + def with_pool_transaction_isolation_level(*_args) + yield end + end + class DummyConnection < ActiveRecord::ConnectionAdapters::AbstractAdapter - private + attr_reader :schema_cache - def create(*) - true + def initialize(*) + super + @schema_cache = DummySchemaCache.new + @pool = DummyPool.new end - def update(*) - true + def self.quote_column_name(column_name) + column_name.to_s end - if ActiveRecord::Base.private_method_defined?(:create_record) - def create_record(*) - true - end - - def update_record(*) - true - end - else - def _create_record(*) - @new_record = false - true - end - - def _update_record(*) - true - end + def pool + @pool end end - else - - # Rails 5+ - - module NoTable - - extend ActiveSupport::Concern - - class DummySchemaCache - - def columns_hash(table_name) - {} - end - - def columns_hash?(table_name) - return false - end - - def data_source_exists?(table_name) - false - end - - def clear_data_source_cache!(table_name) - end + module ClassMethods + def connection + @connection ||= DummyConnection.new(nil) end - class DummyConnection < ActiveRecord::ConnectionAdapters::AbstractAdapter - - attr_reader :schema_cache - - def initialize(*) - super - @schema_cache = DummySchemaCache.new - end - - def self.quote_column_name(column_name) - column_name.to_s - end - + def with_connection(**) + yield(connection) end - module ClassMethods - - def connection - @connection ||= DummyConnection.new(nil) - end - - def with_connection(**) - yield(connection) - end - - def destroy(*) - new - end - - def destroy_all(*) - [] - end - - def find_by_sql(*) - [] - end + def destroy(*) + new + end - def _query_by_sql(*) - [] - end + def destroy_all(*) + [] + end - def cached_find_by(*) - nil - end + def find_by_sql(*) + [] + end - def schema_cache - DummySchemaCache.new - end + def _query_by_sql(*) + [] end - def destroy - @destroyed = true - freeze + def cached_find_by(*) + nil end - def reload - self + def schema_cache + DummySchemaCache.new end + end + def destroy + @destroyed = true + freeze + end - private + def reload + self + end - def create(*) - true - end + private - def update(*) - true - end + def create(*) + true + end - def _create_record(*) - @new_record = false - true - end + def update(*) + true + end - def _update_record(*) - true - end + def _create_record(*) + @new_record = false + true + end + def _update_record(*) + true end end - end diff --git a/lib/active_type/object.rb b/lib/active_type/object.rb index c61d961..0bf9108 100644 --- a/lib/active_type/object.rb +++ b/lib/active_type/object.rb @@ -1,7 +1,7 @@ require 'active_type/no_table' require 'active_type/virtual_attributes' require 'active_type/nested_attributes' -require 'active_type/marshalling' if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 +require 'active_type/marshalling' module ActiveType @@ -10,7 +10,7 @@ class Object < ActiveRecord::Base include NoTable include VirtualAttributes include NestedAttributes - include Marshalling::Methods if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 + include Marshalling::Methods end diff --git a/lib/active_type/record.rb b/lib/active_type/record.rb index 5631a2a..8680fe1 100644 --- a/lib/active_type/record.rb +++ b/lib/active_type/record.rb @@ -2,7 +2,7 @@ require 'active_type/record_extension' require 'active_type/nested_attributes' require 'active_type/change_association' -require 'active_type/marshalling' if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 +require 'active_type/marshalling' module ActiveType @@ -14,7 +14,7 @@ class Record < ActiveRecord::Base include NestedAttributes include RecordExtension include ChangeAssociation - include Marshalling::Methods if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 + include Marshalling::Methods end diff --git a/lib/active_type/record_extension/inheritance.rb b/lib/active_type/record_extension/inheritance.rb index c120e64..8b22d73 100644 --- a/lib/active_type/record_extension/inheritance.rb +++ b/lib/active_type/record_extension/inheritance.rb @@ -18,11 +18,7 @@ def self.add_foreign_key_option(extended_record_base_class, scope = nil, options unless options[:foreign_key] || options[:as] options = options.merge(foreign_key: extended_record_base_class.name.foreign_key) end - if ActiveRecord::VERSION::MAJOR > 3 - [options, scope] - else - [options] - end + [options, scope] end module ClassMethods @@ -66,7 +62,7 @@ def descends_from_active_record? def has_many(name, scope=nil, *args, &extension) new_args, new_scope = Inheritance.add_foreign_key_option(extended_record_base_class, scope, *args) - if ActiveRecord::VERSION::MAJOR <= 3 || new_scope.nil? + if new_scope.nil? super(name, **new_args, &extension) else super(name, new_scope, **new_args, &extension) @@ -75,7 +71,7 @@ def has_many(name, scope=nil, *args, &extension) def has_one(name, scope=nil, *args, &extension) new_args, new_scope = Inheritance.add_foreign_key_option(extended_record_base_class, scope, *args) - if ActiveRecord::VERSION::MAJOR <= 3 || new_scope.nil? + if new_scope.nil? super(name, **new_args, &extension) else super(name, new_scope, **new_args, &extension) @@ -84,79 +80,48 @@ def has_one(name, scope=nil, *args, &extension) private - if ActiveRecord::VERSION::MAJOR < 5 - - def find_sti_class(type_name) - sti_class = super - - # Consider this class hierarchy - # class Parent < ActiveRecord::Base; end - # class Child < Parent; end - # class ExtendedParent < ActiveType::Record[Parent]; end - # class ExtendedChild < ActiveType::Record[Child]; end - if self < sti_class - # i.e. ExtendendChild.find(child.id) - # => self = ExtendedChild; sti_class = Child - # instantiate as ExtendedChild - self - elsif sti_class < extended_record_base_class - # i.e. ExtendedParent.find(child.id) - # => sti_class = Child; self = ExtendedParent; extended_record_base_class = Parent - # There is no really good solution here, since we cannot instantiate as both ExtendedParent - # and Child. We opt to instantiate as ExtendedParent, since the other option can be - # achieved by using Parent.find(child.id) - self + # Rails 5 find_sti_class does a sanity check for proper inheritance that fails for + # our usecase + # copied from activerecord/lib/active_record/inheritance.rb + def find_sti_class(type_name) + type_name = base_class.type_for_attribute(inheritance_column).cast(type_name) + subclass = begin + if store_full_sti_class + type_name.constantize else - sti_class + compute_type(type_name) end + rescue NameError + raise ActiveRecord::SubclassNotFound, + "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \ + "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \ + "Please rename this column if you didn't intend it to be used for storing the inheritance class " \ + "or overwrite #{name}.inheritance_column to use another column for that information." end - - else - - # Rails 5 find_sti_class does a sanity check for proper inheritance that fails for - # our usecase - # copied from activerecord/lib/active_record/inheritance.rb - def find_sti_class(type_name) - type_name = base_class.type_for_attribute(inheritance_column).cast(type_name) - subclass = begin - if store_full_sti_class - type_name.constantize - else - compute_type(type_name) - end - rescue NameError - raise ActiveRecord::SubclassNotFound, - "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \ - "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \ - "Please rename this column if you didn't intend it to be used for storing the inheritance class " \ - "or overwrite #{name}.inheritance_column to use another column for that information." - end - #### our code starts here - # Consider this class hierarchy - # class Parent < ActiveRecord::Base; end - # class Child < Parent; end - # class ExtendedParent < ActiveType::Record[Parent]; end - # class ExtendedChild < ActiveType::Record[Child]; end - if self < subclass - # i.e. ExtendendChild.find(child.id) - # => self = ExtendedChild; subclass = Child - # instantiate as ExtendedChild - subclass = self - elsif subclass < extended_record_base_class - # i.e. ExtendedParent.find(child.id) - # => subclass = Child; self = ExtendedParent; extended_record_base_class = Parent - # There is no really good solution here, since we cannot instantiate as both ExtendedParent - # and Child. We opt to instantiate as ExtendedParent, since the other option can be - # achieved by using Parent.find(child.id) - subclass = self - end - #### our code ends here - unless subclass == self || descendants.include?(subclass) - raise ActiveRecord::SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}" - end - subclass + #### our code starts here + # Consider this class hierarchy + # class Parent < ActiveRecord::Base; end + # class Child < Parent; end + # class ExtendedParent < ActiveType::Record[Parent]; end + # class ExtendedChild < ActiveType::Record[Child]; end + if self < subclass + # i.e. ExtendendChild.find(child.id) + # => self = ExtendedChild; subclass = Child + # instantiate as ExtendedChild + subclass = self + elsif subclass < extended_record_base_class + # i.e. ExtendedParent.find(child.id) + # => subclass = Child; self = ExtendedParent; extended_record_base_class = Parent + # There is no really good solution here, since we cannot instantiate as both ExtendedParent + # and Child. We opt to instantiate as ExtendedParent, since the other option can be + # achieved by using Parent.find(child.id) + subclass = self end - + #### our code ends here + unless subclass == self || descendants.include?(subclass) + raise ActiveRecord::SubclassNotFound, "Invalid single-table inheritance type: #{subclass.name} is not a subclass of #{name}" + end + subclass end end diff --git a/lib/active_type/type_caster.rb b/lib/active_type/type_caster.rb index 29331c3..c453b6b 100644 --- a/lib/active_type/type_caster.rb +++ b/lib/active_type/type_caster.rb @@ -2,13 +2,7 @@ module ActiveType class TypeCaster def self.get(type) - native_caster = if ActiveRecord::VERSION::STRING < '4.2' - NativeCasters::DelegateToColumn.new(type) - elsif ActiveRecord::VERSION::STRING < '5' - NativeCasters::DelegateToRails4Type.new(type) - else - NativeCasters::DelegateToRails5Type.new(type) - end + native_caster = NativeCasters::DelegateToRailsType.new(type) new(type, native_caster) end @@ -104,7 +98,7 @@ def type_cast_from_user(value) # Adapter for Rails 5+. # In these versions, casting logic lives in subclasses of ActiveRecord::Type::Value - class DelegateToRails5Type + class DelegateToRailsType def initialize(type) @active_record_type = lookup(type) diff --git a/lib/active_type/version.rb b/lib/active_type/version.rb index 7e90795..bf3a068 100644 --- a/lib/active_type/version.rb +++ b/lib/active_type/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActiveType - VERSION = '2.6.5' + VERSION = '2.7.0' end diff --git a/lib/active_type/virtual_attributes.rb b/lib/active_type/virtual_attributes.rb index 15a6141..63d08b5 100644 --- a/lib/active_type/virtual_attributes.rb +++ b/lib/active_type/virtual_attributes.rb @@ -189,34 +189,24 @@ def [](name) read_existing_virtual_attribute(name) { super } end - if ActiveRecord::VERSION::STRING >= '4.2.0' - def _read_attribute(name) - read_existing_virtual_attribute(name) { super } - end + def _read_attribute(name) + read_existing_virtual_attribute(name) { super } end - if ActiveRecord::VERSION::STRING < '4.2.0' || ActiveRecord::VERSION::STRING >= '6.1.0' - # in 6.1, read_attribute does not call _read_attribute - def read_attribute(name) - read_existing_virtual_attribute(name) { super } - end + def read_attribute(name) + read_existing_virtual_attribute(name) { super } end def []=(name, value) write_existing_virtual_attribute(name, value) { super } end - if ActiveRecord::VERSION::STRING >= '5.2.0' - def _write_attribute(name, value) - write_existing_virtual_attribute(name, value) { super } - end + def _write_attribute(name, value) + write_existing_virtual_attribute(name, value) { super } end - if ActiveRecord::VERSION::STRING < '5.2.0' || ActiveRecord::VERSION::STRING >= '6.1.0' - # in 6.1, write_attribute does not call _write_attribute - def write_attribute(name, value) - write_existing_virtual_attribute(name, value) { super } - end + def write_attribute(name, value) + write_existing_virtual_attribute(name, value) { super } end def attributes @@ -252,14 +242,12 @@ def attribute_changed?(attr, **) end end - if ActiveRecord::VERSION::MAJOR >= 4 - def changes_applied - super + def changes_applied + super - virtual_attributes.each do |attr, _| - value = read_virtual_attribute(attr) - virtual_attributes_were[attr] = value.duplicable? ? value.clone : value - end + virtual_attributes.each do |attr, _| + value = read_virtual_attribute(attr) + virtual_attributes_were[attr] = value.duplicable? ? value.clone : value end end diff --git a/spec/active_type/change_association_spec.rb b/spec/active_type/change_association_spec.rb index 3c7be4b..7f5ea2b 100644 --- a/spec/active_type/change_association_spec.rb +++ b/spec/active_type/change_association_spec.rb @@ -14,9 +14,7 @@ class Record < ActiveRecord::Base has_many :children, class_name: 'ChangeAssociationSpec::Child', dependent: :destroy has_one :lone_child, class_name: 'ChangeAssociationSpec::Child' - if ActiveRecord::VERSION::MAJOR > 3 - has_many :nice_children, -> { where(nice: true) }, class_name: 'ChangeAssociationSpec::Child' - end + has_many :nice_children, -> { where(nice: true) }, class_name: 'ChangeAssociationSpec::Child' has_many :pictures, class_name: 'ChangeAssociationSpec::Picture', as: :imageable has_one :lone_picture, class_name: 'ChangeAssociationSpec::Picture', as: :imageable @@ -137,71 +135,69 @@ def self.name expect(extended_class.first.lone_picture).to be_instance_of(ExtendedPicture) end - if ActiveRecord::VERSION::MAJOR > 3 - it 'retains scopes of the existing association' do - record = Record.create - Child.create(record: record, nice: true) - Child.create(record: record, nice: false) - expect(record.nice_children.size).to eq 1 - - extended_class = Class.new(ActiveType::Record[Record]) do - def self.name - 'ExtendedRecord' - end + it 'retains scopes of the existing association' do + record = Record.create + Child.create(record: record, nice: true) + Child.create(record: record, nice: false) + expect(record.nice_children.size).to eq 1 - change_association :nice_children, class_name: 'ChangeAssociationSpec::ExtendedChild' + extended_class = Class.new(ActiveType::Record[Record]) do + def self.name + 'ExtendedRecord' end - extended_nice_children = extended_class.first.nice_children - - expect(extended_nice_children.size).to eq 1 - expect(extended_nice_children.first).to be_instance_of(ExtendedChild) + change_association :nice_children, class_name: 'ChangeAssociationSpec::ExtendedChild' end - it 'can override scopes' do - record = Record.create - Child.create(record: record, nice: true) - Child.create(record: record, nice: false) - Child.create(record: record, nice: false) - expect(record.nice_children.size).to eq 1 + extended_nice_children = extended_class.first.nice_children - extended_class = Class.new(ActiveType::Record[Record]) do - def self.name - 'ExtendedRecord' - end + expect(extended_nice_children.size).to eq 1 + expect(extended_nice_children.first).to be_instance_of(ExtendedChild) + end - # today is opposite day - change_association :nice_children, -> { where(nice: false) }, class_name: 'ChangeAssociationSpec::ExtendedChild' - end + it 'can override scopes' do + record = Record.create + Child.create(record: record, nice: true) + Child.create(record: record, nice: false) + Child.create(record: record, nice: false) + expect(record.nice_children.size).to eq 1 - extended_nice_children = extended_class.first.nice_children + extended_class = Class.new(ActiveType::Record[Record]) do + def self.name + 'ExtendedRecord' + end - expect(extended_nice_children.size).to eq 2 - expect(extended_nice_children.first).to be_instance_of(ExtendedChild) + # today is opposite day + change_association :nice_children, -> { where(nice: false) }, class_name: 'ChangeAssociationSpec::ExtendedChild' end - it 'does not raise an error when overriding scopes without new_options' do - record = Record.create - Child.create(record: record, nice: true) - Child.create(record: record, nice: false) - Child.create(record: record, nice: false) - expect(record.nice_children.size).to eq 1 + extended_nice_children = extended_class.first.nice_children - extended_proc = ->(_class) do - def self.name - 'ExtendedRecord' - end + expect(extended_nice_children.size).to eq 2 + expect(extended_nice_children.first).to be_instance_of(ExtendedChild) + end - # today is opposite day - change_association :nice_children, -> { where(nice: false) } - end + it 'does not raise an error when overriding scopes without new_options' do + record = Record.create + Child.create(record: record, nice: true) + Child.create(record: record, nice: false) + Child.create(record: record, nice: false) + expect(record.nice_children.size).to eq 1 - expect { @extended_class = Class.new(ActiveType::Record[Record], &extended_proc) }.not_to raise_error + extended_proc = ->(_class) do + def self.name + 'ExtendedRecord' + end - extended_nice_children = @extended_class.first.nice_children - expect(extended_nice_children.size).to eq 2 - expect(extended_nice_children.first).to be_instance_of(Child) + # today is opposite day + change_association :nice_children, -> { where(nice: false) } end + + expect { @extended_class = Class.new(ActiveType::Record[Record], &extended_proc) }.not_to raise_error + + extended_nice_children = @extended_class.first.nice_children + expect(extended_nice_children.size).to eq 2 + expect(extended_nice_children.first).to be_instance_of(Child) end end diff --git a/spec/active_type/nested_attributes_spec.rb b/spec/active_type/nested_attributes_spec.rb index 81a6c0a..59d4a4e 100644 --- a/spec/active_type/nested_attributes_spec.rb +++ b/spec/active_type/nested_attributes_spec.rb @@ -13,11 +13,7 @@ class Record < ActiveRecord::Base def check_fail if fail_on_save == true - if ActiveRecord::VERSION::MAJOR >= 5 - throw :abort - else - false - end + throw :abort end end diff --git a/spec/active_type/object_spec.rb b/spec/active_type/object_spec.rb index f980a5c..cc25dba 100644 --- a/spec/active_type/object_spec.rb +++ b/spec/active_type/object_spec.rb @@ -4,9 +4,7 @@ module ObjectSpec def self.type - if ActiveRecord::VERSION::MAJOR >= 5 - @type ||= ActiveModel::Type::Value.new - end + @type ||= ActiveModel::Type::Value.new end class Object < ActiveType::Object @@ -107,30 +105,28 @@ class ObjectWithOptionalBelongsTo < Object end - if ActiveRecord::VERSION::STRING >= '7.1.0' - ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key - - class ObjectWithRequiredBelongsToFlippedValidatesForeignKey < Object - BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key + ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key - attribute :child_id, :integer + class ObjectWithRequiredBelongsToFlippedValidatesForeignKey < Object + BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key - belongs_to :child, optional: false + attribute :child_id, :integer - end + belongs_to :child, optional: false - class ObjectWithOptionalBelongsToFlippedValidatesForeignKey < Object - BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key + end - attribute :child_id, :integer + class ObjectWithOptionalBelongsToFlippedValidatesForeignKey < Object + BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key - belongs_to :child, optional: true + attribute :child_id, :integer - end + belongs_to :child, optional: true - ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key end + ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key + class ObjectWithUnsupportedTypes < Object attribute :virtual_array, :array attribute :virtual_hash, :hash @@ -413,20 +409,18 @@ class ObjectWithUnsupportedTypes < Object it_should_behave_like 'an optional belongs_to association', :child, ObjectSpec::Child end - if ActiveRecord::VERSION::STRING >= '7.1.0' - v = ObjectSpec::ObjectWithRequiredBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY - describe "#belongs_to, optional: false, belongs_to_required_validates_foreign_key: #{v}" do - subject { ObjectSpec::ObjectWithRequiredBelongsToFlippedValidatesForeignKey.new } + v = ObjectSpec::ObjectWithRequiredBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY + describe "#belongs_to, optional: false, belongs_to_required_validates_foreign_key: #{v}" do + subject { ObjectSpec::ObjectWithRequiredBelongsToFlippedValidatesForeignKey.new } - it_should_behave_like 'a required belongs_to association', :child, ObjectSpec::Child - end + it_should_behave_like 'a required belongs_to association', :child, ObjectSpec::Child + end - v = ObjectSpec::ObjectWithOptionalBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY - describe "#belongs_to, optional: true, belongs_to_required_validates_foreign_key: #{v}" do - subject { ObjectSpec::ObjectWithOptionalBelongsToFlippedValidatesForeignKey.new } + v = ObjectSpec::ObjectWithOptionalBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY + describe "#belongs_to, optional: true, belongs_to_required_validates_foreign_key: #{v}" do + subject { ObjectSpec::ObjectWithOptionalBelongsToFlippedValidatesForeignKey.new } - it_should_behave_like 'an optional belongs_to association', :child, ObjectSpec::Child - end + it_should_behave_like 'an optional belongs_to association', :child, ObjectSpec::Child end describe '#save' do @@ -449,12 +443,8 @@ class ObjectWithUnsupportedTypes < Object %w[before_validation before_save].each do |callback| it "aborts the chain when #{callback} returns false" do - if ActiveRecord::VERSION::MAJOR >= 5 - allow(subject).to receive("#{callback}_callback") do - throw(:abort) - end - else - allow(subject).to receive_messages("#{callback}_callback" => false) + allow(subject).to receive("#{callback}_callback") do + throw(:abort) end expect(subject.save).to be_falsey @@ -488,14 +478,9 @@ class ObjectWithUnsupportedTypes < Object describe '.find' do it 'raises an error' do - error = if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 1 - ActiveRecord::UnknownPrimaryKey - else - ActiveRecord::RecordNotFound - end expect do ObjectSpec::Object.find(1) - end.to raise_error(error) + end.to raise_error(ActiveRecord::RecordNotFound) end end @@ -557,53 +542,48 @@ class ObjectWithUnsupportedTypes < Object end end - if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 - context 'for 6.1 marshalling' do - before do - ActiveRecord::Marshalling.format_version = 6.1 - end - - include_examples "marshalling attributes" + context 'for 6.1 marshalling' do + before do + ActiveRecord::Marshalling.format_version = 6.1 end - context 'for 7.1 marshalling' do - before do - ActiveRecord::Marshalling.format_version = 7.1 - end + include_examples "marshalling attributes" + end - include_examples "marshalling attributes" + context 'for 7.1 marshalling' do + before do + ActiveRecord::Marshalling.format_version = 7.1 end - describe "loading a object marshalled with format version 6.1, but the current version is 7.1" do - it "marshals attributes properly" do - object = ObjectSpec::Object.create(virtual_attribute: "foobar") + include_examples "marshalling attributes" + end - ActiveRecord::Marshalling.format_version = 6.1 - serialized_object = Marshal.dump(object) + describe "loading a object marshalled with format version 6.1, but the current version is 7.1" do + it "marshals attributes properly" do + object = ObjectSpec::Object.create(virtual_attribute: "foobar") - ActiveRecord::Marshalling.format_version = 7.1 - deserialized_object = Marshal.load(serialized_object) + ActiveRecord::Marshalling.format_version = 6.1 + serialized_object = Marshal.dump(object) - expect(deserialized_object.virtual_attribute).to eq "foobar" - end + ActiveRecord::Marshalling.format_version = 7.1 + deserialized_object = Marshal.load(serialized_object) + + expect(deserialized_object.virtual_attribute).to eq "foobar" end + end - describe "loading a object marshalled with format version 7.1, but the current version is 6.1" do - it "marshals attributes properly" do - object = ObjectSpec::Object.create(virtual_attribute: "foobar") + describe "loading a object marshalled with format version 7.1, but the current version is 6.1" do + it "marshals attributes properly" do + object = ObjectSpec::Object.create(virtual_attribute: "foobar") - ActiveRecord::Marshalling.format_version = 7.1 - serialized_object = Marshal.dump(object) + ActiveRecord::Marshalling.format_version = 7.1 + serialized_object = Marshal.dump(object) - ActiveRecord::Marshalling.format_version = 6.1 - deserialized_object = Marshal.load(serialized_object) + ActiveRecord::Marshalling.format_version = 6.1 + deserialized_object = Marshal.load(serialized_object) - expect(deserialized_object.virtual_attribute).to eq "foobar" - end + expect(deserialized_object.virtual_attribute).to eq "foobar" end - - else - include_examples "marshalling attributes" end end diff --git a/spec/active_type/record_spec.rb b/spec/active_type/record_spec.rb index 77311b0..10b9b4d 100644 --- a/spec/active_type/record_spec.rb +++ b/spec/active_type/record_spec.rb @@ -4,9 +4,7 @@ module RecordSpec def self.type - if ActiveRecord::VERSION::MAJOR >= 5 - @type ||= ActiveModel::Type::Value.new - end + @type ||= ActiveModel::Type::Value.new end class Record < ActiveType::Record @@ -68,29 +66,27 @@ class RecordWithOptionalBelongsTo < Record end - if ActiveRecord::VERSION::STRING >= '7.1.0' - ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key - - class RecordWithRequiredBelongsToFlippedValidatesForeignKey < Record - BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key + ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key - attribute :child_id, :integer + class RecordWithRequiredBelongsToFlippedValidatesForeignKey < Record + BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key - belongs_to :child, optional: false + attribute :child_id, :integer - end + belongs_to :child, optional: false - class RecordWithOptionalBelongsToFlippedValidatesForeignKey < Record - BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key + end - attribute :child_id, :integer + class RecordWithOptionalBelongsToFlippedValidatesForeignKey < Record + BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY = ActiveRecord.belongs_to_required_validates_foreign_key - belongs_to :child, optional: true + attribute :child_id, :integer - end + belongs_to :child, optional: true - ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key end + + ActiveRecord.belongs_to_required_validates_foreign_key = !ActiveRecord.belongs_to_required_validates_foreign_key end @@ -314,20 +310,18 @@ class RecordWithOptionalBelongsToFlippedValidatesForeignKey < Record it_should_behave_like 'an optional belongs_to association', :child, RecordSpec::Child end - if ActiveRecord::VERSION::STRING >= '7.1.0' - v = RecordSpec::RecordWithRequiredBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY - describe "#belongs_to, optional: false, belongs_to_required_validates_foreign_key: #{v}" do - subject { RecordSpec::RecordWithRequiredBelongsToFlippedValidatesForeignKey.new } + v = RecordSpec::RecordWithRequiredBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY + describe "#belongs_to, optional: false, belongs_to_required_validates_foreign_key: #{v}" do + subject { RecordSpec::RecordWithRequiredBelongsToFlippedValidatesForeignKey.new } - it_should_behave_like 'a required belongs_to association', :child, RecordSpec::Child - end + it_should_behave_like 'a required belongs_to association', :child, RecordSpec::Child + end - v = RecordSpec::RecordWithOptionalBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY - describe "#belongs_to, optional: true, belongs_to_required_validates_foreign_key: #{v}" do - subject { RecordSpec::RecordWithOptionalBelongsToFlippedValidatesForeignKey.new } + v = RecordSpec::RecordWithOptionalBelongsToFlippedValidatesForeignKey::BELONGS_TO_REQUIRED_VALIDATES_FOREIGN_KEY + describe "#belongs_to, optional: true, belongs_to_required_validates_foreign_key: #{v}" do + subject { RecordSpec::RecordWithOptionalBelongsToFlippedValidatesForeignKey.new } - it_should_behave_like 'an optional belongs_to association', :child, RecordSpec::Child - end + it_should_behave_like 'an optional belongs_to association', :child, RecordSpec::Child end it 'can access virtual attributes after .find' do @@ -336,19 +330,17 @@ class RecordWithOptionalBelongsToFlippedValidatesForeignKey < Record expect(subject.class.find(subject.id).virtual_string).to eq(nil) end - if ActiveRecord::VERSION::MAJOR >= 5 - describe '#ar_attribute' do - it 'delegates to ActiveRecord\'s original .attribute method' do - klass = Class.new(RecordSpec::Record) do - ar_attribute :ar_type, RecordSpec.type - end - subject = klass.new + describe '#ar_attribute' do + it 'delegates to ActiveRecord\'s original .attribute method' do + klass = Class.new(RecordSpec::Record) do + ar_attribute :ar_type, RecordSpec.type + end + subject = klass.new - expect(RecordSpec.type).to receive(:cast).with('input').and_return('output') - subject.ar_type = 'input' + expect(RecordSpec.type).to receive(:cast).with('input').and_return('output') + subject.ar_type = 'input' - expect(subject.ar_type).to eq('output') - end + expect(subject.ar_type).to eq('output') end end @@ -404,60 +396,56 @@ class RecordWithOptionalBelongsToFlippedValidatesForeignKey < Record end end - if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 - context 'for 6.1 marshalling' do - before do - ActiveRecord::Marshalling.format_version = 6.1 - end - - include_examples "marshalling attributes" + context 'for 6.1 marshalling' do + before do + ActiveRecord::Marshalling.format_version = 6.1 end - context 'for 7.1 marshalling' do - before do - ActiveRecord::Marshalling.format_version = 7.1 - end + include_examples "marshalling attributes" + end - include_examples "marshalling attributes" + context 'for 7.1 marshalling' do + before do + ActiveRecord::Marshalling.format_version = 7.1 end - describe "loading a object marshalled with format version 6.1, but the current version is 7.1" do - it "marshals attributes properly" do - object = RecordSpec::Record.create!( - virtual_string: "foo", - persisted_string: "bar" - ) + include_examples "marshalling attributes" + end - ActiveRecord::Marshalling.format_version = 6.1 - serialized_object = Marshal.dump(object) + describe "loading a object marshalled with format version 6.1, but the current version is 7.1" do + it "marshals attributes properly" do + object = RecordSpec::Record.create!( + virtual_string: "foo", + persisted_string: "bar" + ) - ActiveRecord::Marshalling.format_version = 7.1 - deserialized_object = Marshal.load(serialized_object) + ActiveRecord::Marshalling.format_version = 6.1 + serialized_object = Marshal.dump(object) - expect(deserialized_object.virtual_string).to eq "foo" - expect(deserialized_object.persisted_string).to eq "bar" - end + ActiveRecord::Marshalling.format_version = 7.1 + deserialized_object = Marshal.load(serialized_object) + + expect(deserialized_object.virtual_string).to eq "foo" + expect(deserialized_object.persisted_string).to eq "bar" end + end - describe "loading a object marshalled with format version 7.1, but the current version is 6.1" do - it "marshals attributes properly" do - object = RecordSpec::Record.create!( - virtual_string: "foo", - persisted_string: "bar" - ) + describe "loading a object marshalled with format version 7.1, but the current version is 6.1" do + it "marshals attributes properly" do + object = RecordSpec::Record.create!( + virtual_string: "foo", + persisted_string: "bar" + ) - ActiveRecord::Marshalling.format_version = 7.1 - serialized_object = Marshal.dump(object) + ActiveRecord::Marshalling.format_version = 7.1 + serialized_object = Marshal.dump(object) - ActiveRecord::Marshalling.format_version = 6.1 - deserialized_object = Marshal.load(serialized_object) + ActiveRecord::Marshalling.format_version = 6.1 + deserialized_object = Marshal.load(serialized_object) - expect(deserialized_object.virtual_string).to eq "foo" - expect(deserialized_object.persisted_string).to eq "bar" - end + expect(deserialized_object.virtual_string).to eq "foo" + expect(deserialized_object.persisted_string).to eq "bar" end - else - include_examples "marshalling attributes" end end end diff --git a/spec/active_type/util_spec.rb b/spec/active_type/util_spec.rb index bf4b5f4..44ab217 100644 --- a/spec/active_type/util_spec.rb +++ b/spec/active_type/util_spec.rb @@ -222,24 +222,20 @@ class AssociatedRecord < ActiveRecord::Base expect(extended_record).to be_readonly end - if ActiveRecord::VERSION::MAJOR >= 7 || (ActiveRecord::VERSION::MAJOR == 6 && ActiveRecord::VERSION::MINOR >= 1) - it 'preserves the strict loading status' do - base_record = UtilSpec::BaseRecord.create! - base_record.strict_loading! - expect(base_record).to be_strict_loading - extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord) - expect(extended_record).to be_strict_loading - end + it 'preserves the strict loading status' do + base_record = UtilSpec::BaseRecord.create! + base_record.strict_loading! + expect(base_record).to be_strict_loading + extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord) + expect(extended_record).to be_strict_loading end - if ActiveRecord::VERSION::MAJOR >= 7 - it 'preserves the strict loading mode' do - base_record = UtilSpec::BaseRecord.create! - base_record.strict_loading!(mode: :n_plus_one_only) - expect(base_record.strict_loading_mode).to eq :n_plus_one_only - extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord) - expect(extended_record.strict_loading_mode).to eq :n_plus_one_only - end + it 'preserves the strict loading mode' do + base_record = UtilSpec::BaseRecord.create! + base_record.strict_loading!(mode: :n_plus_one_only) + expect(base_record.strict_loading_mode).to eq :n_plus_one_only + extended_record = ActiveType::Util.cast(base_record, UtilSpec::ExtendedRecord) + expect(extended_record.strict_loading_mode).to eq :n_plus_one_only end context 'altering the record used as base for casting' do diff --git a/spec/shared_examples/accessors.rb b/spec/shared_examples/accessors.rb index 688f206..d9dbdc0 100644 --- a/spec/shared_examples/accessors.rb +++ b/spec/shared_examples/accessors.rb @@ -28,15 +28,13 @@ end end - if ActiveRecord::VERSION::STRING >= '4.2.0' - # Rails 4.2 introduced this internal reader method for performance reasons. - # https://github.com/rails/rails/commit/08576b94ad4f19dfc368619d7751e211d23dcad8 - # It is called by `read_attribute` and other ActiveRecord methods, so we test its behavior explicitly. - it 'allows reading via _read_attribute' do - attributes.each do |key, value| - subject.send("#{key}=", value) - expect(subject._read_attribute(key.to_s)).to eq(value) - end + # Rails 4.2 introduced this internal reader method for performance reasons. + # https://github.com/rails/rails/commit/08576b94ad4f19dfc368619d7751e211d23dcad8 + # It is called by `read_attribute` and other ActiveRecord methods, so we test its behavior explicitly. + it 'allows reading via _read_attribute' do + attributes.each do |key, value| + subject.send("#{key}=", value) + expect(subject._read_attribute(key.to_s)).to eq(value) end end @@ -47,15 +45,13 @@ end end - if ActiveRecord::VERSION::STRING >= '5.2.0' - # Rails 5.2 introduced this internal writer method for performance reasons. - # https://github.com/rails/rails/commit/c879649a733d982fba9e70f5a280d13636b67c37 - # It is called by `write_attribute` and other ActiveRecord methods, so we test its behavior explicitly. - it 'allows writing via _write_attribute' do - attributes.each do |key, value| - subject._write_attribute(key.to_s, value) - expect(subject.send(key)).to eq(value) - end + # Rails 5.2 introduced this internal writer method for performance reasons. + # https://github.com/rails/rails/commit/c879649a733d982fba9e70f5a280d13636b67c37 + # It is called by `write_attribute` and other ActiveRecord methods, so we test its behavior explicitly. + it 'allows writing via _write_attribute' do + attributes.each do |key, value| + subject._write_attribute(key.to_s, value) + expect(subject.send(key)).to eq(value) end end diff --git a/spec/shared_examples/constructor.rb b/spec/shared_examples/constructor.rb index ba2f93a..8a629de 100644 --- a/spec/shared_examples/constructor.rb +++ b/spec/shared_examples/constructor.rb @@ -12,19 +12,15 @@ end end - if ActiveRecord::VERSION::MAJOR >= 4 - - it 'raises on unpermitted parameters' do - params = ProtectedParams.new(attributes) - expect { subject.new(params) }.to raise_error(ActiveModel::ForbiddenAttributesError) - end - - it 'accepts permitted parameters' do - params = ProtectedParams.new(attributes) - params.permit! - expect { subject.new(params) }.to_not raise_error - end + it 'raises on unpermitted parameters' do + params = ProtectedParams.new(attributes) + expect { subject.new(params) }.to raise_error(ActiveModel::ForbiddenAttributesError) + end + it 'accepts permitted parameters' do + params = ProtectedParams.new(attributes) + params.permit! + expect { subject.new(params) }.to_not raise_error end end diff --git a/spec/shared_examples/dirty_tracking.rb b/spec/shared_examples/dirty_tracking.rb index 0c593cf..2d193aa 100644 --- a/spec/shared_examples/dirty_tracking.rb +++ b/spec/shared_examples/dirty_tracking.rb @@ -8,18 +8,11 @@ describe '#virtual_attribute_was' do - if ActiveRecord::VERSION::MAJOR >= 4 - it 'returns value before changes were applied' do - expect(subject.virtual_attribute_was).to be_nil - subject.virtual_attribute = 'foo' - subject.changes_applied - expect(subject.virtual_attribute_was).to eq('foo') - end - else - it 'returns nil' do - subject.virtual_attribute = 'foo' - expect(subject.virtual_attribute_was).to be_nil - end + it 'returns value before changes were applied' do + expect(subject.virtual_attribute_was).to be_nil + subject.virtual_attribute = 'foo' + subject.changes_applied + expect(subject.virtual_attribute_was).to eq('foo') end end @@ -36,12 +29,10 @@ expect(subject.virtual_attribute_changed?).to be_falsey end - if ActiveRecord::VERSION::MAJOR >= 4 - it 'returns false after changes were applied' do - subject.virtual_attribute = 'foo' - subject.changes_applied - expect(subject.virtual_attribute_changed?).to eq(false) - end + it 'returns false after changes were applied' do + subject.virtual_attribute = 'foo' + subject.changes_applied + expect(subject.virtual_attribute_changed?).to eq(false) end end @@ -66,13 +57,11 @@ expect(subject.changed?).to eq(false) end - if ActiveRecord::VERSION::MAJOR >= 4 - context 'after applying changes' do - it 'returns false' do - subject.virtual_attribute = 'foo' - subject.changes_applied - expect(subject.changed?).to eq(false) - end + context 'after applying changes' do + it 'returns false' do + subject.virtual_attribute = 'foo' + subject.changes_applied + expect(subject.changed?).to eq(false) end end @@ -92,13 +81,11 @@ expect(subject.changes).to eq({}) end - if ActiveRecord::VERSION::MAJOR >= 4 - context 'after applying changes' do - it 'returns empty hash' do - subject.virtual_attribute = 'foo' - subject.changes_applied - expect(subject.changes).to eq({}) - end + context 'after applying changes' do + it 'returns empty hash' do + subject.virtual_attribute = 'foo' + subject.changes_applied + expect(subject.changes).to eq({}) end end diff --git a/spec/shared_examples/mass_assignment.rb b/spec/shared_examples/mass_assignment.rb index 0bfd4e1..e3aaaa4 100644 --- a/spec/shared_examples/mass_assignment.rb +++ b/spec/shared_examples/mass_assignment.rb @@ -8,19 +8,15 @@ end end - if ActiveRecord::VERSION::MAJOR >= 4 - - it 'raises on unpermitted parameters' do - params = ProtectedParams.new(attributes) - expect { subject.attributes = params }.to raise_error(ActiveModel::ForbiddenAttributesError) - end - - it 'accepts permitted parameters' do - params = ProtectedParams.new(attributes) - params.permit! - expect { subject.attributes = params }.to_not raise_error - end + it 'raises on unpermitted parameters' do + params = ProtectedParams.new(attributes) + expect { subject.attributes = params }.to raise_error(ActiveModel::ForbiddenAttributesError) + end + it 'accepts permitted parameters' do + params = ProtectedParams.new(attributes) + params.permit! + expect { subject.attributes = params }.to_not raise_error end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 92b3795..35223da 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -40,7 +40,6 @@ def self.version_agnostic_index_nested_attribute_errors=(zone) end ActiveRecord.version_agnostic_default_timezone = :local -ActiveRecord::Base.raise_in_transactional_callbacks = true if ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ActiveRecord::VERSION::MAJOR < 5 Dir["#{File.dirname(__FILE__)}/support/*.rb"].each {|f| require f} Dir["#{File.dirname(__FILE__)}/shared_examples/*.rb"].each {|f| require f}