From d89b8931f06ab7b7ae01fb5d6e1186eccbfa2422 Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Fri, 30 Jan 2026 17:55:38 -0300 Subject: [PATCH 1/7] Add ActiveRecord Normalize to forms --- .github/workflows/ci.yml | 88 ++----------------- lib/yaaf/form.rb | 3 + spec/gemfiles/rails_6_0.gemfile | 6 -- spec/gemfiles/rails_6_1.gemfile | 6 -- spec/gemfiles/rails_7_0.gemfile | 6 -- .../{rails_5_2.gemfile => rails_8_1.gemfile} | 3 +- spec/support/forms.rb | 1 + spec/support/forms/with_normalize_form.rb | 17 ++++ spec/yaaf/normalization_spec.rb | 48 ++++++++++ yaaf.gemspec | 6 +- 10 files changed, 81 insertions(+), 103 deletions(-) delete mode 100644 spec/gemfiles/rails_6_0.gemfile delete mode 100644 spec/gemfiles/rails_6_1.gemfile delete mode 100644 spec/gemfiles/rails_7_0.gemfile rename spec/gemfiles/{rails_5_2.gemfile => rails_8_1.gemfile} (51%) create mode 100644 spec/support/forms/with_normalize_form.rb create mode 100644 spec/yaaf/normalization_spec.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6e8e60..fd7e90e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,103 +12,31 @@ jobs: strategy: fail-fast: false matrix: - gemfile: [rails_5_2.gemfile, rails_6_0.gemfile, rails_6_1.gemfile, rails_7_0.gemfile, rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_main.gemfile] - ruby_version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4'] + gemfile: [rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_8_1.gemfile, rails_main.gemfile] + ruby_version: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4', '4.0'] exclude: - - gemfile: rails_main.gemfile - ruby_version: '2.3' - - gemfile: rails_main.gemfile - ruby_version: '2.4' - - gemfile: rails_main.gemfile - ruby_version: '2.5' - - gemfile: rails_main.gemfile - ruby_version: '2.6' - gemfile: rails_main.gemfile ruby_version: '2.7' - gemfile: rails_main.gemfile ruby_version: '3.0' - gemfile: rails_main.gemfile ruby_version: '3.1' - - gemfile: rails_8_0.gemfile - ruby_version: '2.3' - - gemfile: rails_8_0.gemfile - ruby_version: '2.4' - - gemfile: rails_8_0.gemfile - ruby_version: '2.5' - - gemfile: rails_8_0.gemfile - ruby_version: '2.6' + - gemfile: rails_8_1.gemfile + ruby_version: '2.7' + - gemfile: rails_8_1.gemfile + ruby_version: '3.0' + - gemfile: rails_8_1.gemfile + ruby_version: '3.1' - gemfile: rails_8_0.gemfile ruby_version: '2.7' - gemfile: rails_8_0.gemfile ruby_version: '3.0' - gemfile: rails_8_0.gemfile ruby_version: '3.1' - - gemfile: rails_7_2.gemfile - ruby_version: '2.3' - - gemfile: rails_7_2.gemfile - ruby_version: '2.4' - - gemfile: rails_7_2.gemfile - ruby_version: '2.5' - - gemfile: rails_7_2.gemfile - ruby_version: '2.6' - gemfile: rails_7_2.gemfile ruby_version: '2.7' - gemfile: rails_7_2.gemfile ruby_version: '3.0' - - gemfile: rails_7_1.gemfile - ruby_version: '2.3' - - gemfile: rails_7_1.gemfile - ruby_version: '2.4' - - gemfile: rails_7_1.gemfile - ruby_version: '2.5' - - gemfile: rails_7_1.gemfile - ruby_version: '2.6' - - gemfile: rails_7_0.gemfile - ruby_version: '2.3' - - gemfile: rails_7_0.gemfile - ruby_version: '2.4' - - gemfile: rails_7_0.gemfile - ruby_version: '2.5' - - gemfile: rails_7_0.gemfile - ruby_version: '2.6' - - gemfile: rails_7_0.gemfile - ruby_version: '3.4' - - gemfile: rails_6_1.gemfile - ruby_version: '2.3' - - gemfile: rails_6_1.gemfile - ruby_version: '2.4' - - gemfile: rails_6_1.gemfile - ruby_version: '3.1' - - gemfile: rails_6_1.gemfile - ruby_version: '3.2' - - gemfile: rails_6_1.gemfile - ruby_version: '3.3' - - gemfile: rails_6_1.gemfile - ruby_version: '3.4' - - gemfile: rails_6_0.gemfile - ruby_version: '2.3' - - gemfile: rails_6_0.gemfile - ruby_version: '2.4' - - gemfile: rails_6_0.gemfile - ruby_version: '3.0' - - gemfile: rails_6_0.gemfile - ruby_version: '3.1' - - gemfile: rails_6_0.gemfile - ruby_version: '3.2' - - gemfile: rails_6_0.gemfile - ruby_version: '3.3' - - gemfile: rails_6_0.gemfile - ruby_version: '3.4' - - gemfile: rails_5_2.gemfile - ruby_version: '3.0' - - gemfile: rails_5_2.gemfile - ruby_version: '3.1' - - gemfile: rails_5_2.gemfile - ruby_version: '3.2' - - gemfile: rails_5_2.gemfile - ruby_version: '3.3' - - gemfile: rails_5_2.gemfile - ruby_version: '3.4' env: BUNDLE_GEMFILE: spec/gemfiles/${{ matrix.gemfile }} steps: diff --git a/lib/yaaf/form.rb b/lib/yaaf/form.rb index 8e0417d..b425503 100644 --- a/lib/yaaf/form.rb +++ b/lib/yaaf/form.rb @@ -6,6 +6,9 @@ class Form include ::ActiveModel::Model include ::ActiveModel::Validations::Callbacks include ::ActiveRecord::Transactions + include ::ActiveModel::Attributes + include ::ActiveModel::Attributes::Normalization + define_model_callbacks :save delegate :transaction, to: ::ActiveRecord::Base diff --git a/spec/gemfiles/rails_6_0.gemfile b/spec/gemfiles/rails_6_0.gemfile deleted file mode 100644 index d68315d..0000000 --- a/spec/gemfiles/rails_6_0.gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source 'https://rubygems.org' - -gemspec path: '../..' - -gem 'rails', '~> 6.0.0' -gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_6_1.gemfile b/spec/gemfiles/rails_6_1.gemfile deleted file mode 100644 index 617a8b0..0000000 --- a/spec/gemfiles/rails_6_1.gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source 'https://rubygems.org' - -gemspec path: '../..' - -gem 'rails', '~> 6.1.0' -gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_7_0.gemfile b/spec/gemfiles/rails_7_0.gemfile deleted file mode 100644 index abce1b2..0000000 --- a/spec/gemfiles/rails_7_0.gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source 'https://rubygems.org' - -gemspec path: '../..' - -gem 'rails', '~> 7.0.0' -gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_5_2.gemfile b/spec/gemfiles/rails_8_1.gemfile similarity index 51% rename from spec/gemfiles/rails_5_2.gemfile rename to spec/gemfiles/rails_8_1.gemfile index d869b89..63366c8 100644 --- a/spec/gemfiles/rails_5_2.gemfile +++ b/spec/gemfiles/rails_8_1.gemfile @@ -2,5 +2,4 @@ source 'https://rubygems.org' gemspec path: '../..' -gem 'rails', '~> 5.2.0' -gem 'sqlite3', '~> 1.4.2' +gem 'rails', '~> 8.1.0' diff --git a/spec/support/forms.rb b/spec/support/forms.rb index 42d178c..e8bf235 100644 --- a/spec/support/forms.rb +++ b/spec/support/forms.rb @@ -8,3 +8,4 @@ require_relative 'forms/with_callback_exception_raising' require_relative 'forms/custom_transaction_form' require_relative 'forms/user_destroy_form' +require_relative 'forms/with_normalize_form' diff --git a/spec/support/forms/with_normalize_form.rb b/spec/support/forms/with_normalize_form.rb new file mode 100644 index 0000000..897b8f9 --- /dev/null +++ b/spec/support/forms/with_normalize_form.rb @@ -0,0 +1,17 @@ +class WithNormalizeForm < YAAF::Form + attribute :email, :string + attribute :name, :string + + normalizes :email, with: ->(email) { email.strip.downcase } + normalizes :name, with: ->(name) { name.strip.titleize } + + def initialize(args) + super(args) + + @models = [user] + end + + def user + @user ||= User.new(email: email, name: name) + end +end diff --git a/spec/yaaf/normalization_spec.rb b/spec/yaaf/normalization_spec.rb new file mode 100644 index 0000000..dc9b5c9 --- /dev/null +++ b/spec/yaaf/normalization_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +RSpec.describe 'Form with normalization' do + let(:form) { WithNormalizeForm.new(args) } + let(:args) { { email: ' TEST@Example.com ', name: ' john doe ' } } + + describe 'attribute normalization' do + it 'normalizes email on assignment' do + expect(form.email).to eq('test@example.com') + end + + it 'normalizes name on assignment' do + expect(form.name).to eq('John Doe') + end + end + + describe '#save' do + subject { form.save } + + it 'saves with normalized values' do + expect(subject).to be true + expect(User.last.email).to eq('test@example.com') + expect(User.last.name).to eq('John Doe') + end + end + + describe '#valid?' do + it 'validates with normalized values' do + expect(form.valid?).to be true + end + end + + context 'when updating attributes' do + it 'normalizes new values' do + form.email = ' test@example.com ' + expect(form.email).to eq('test@example.com') + end + end + + context 'with nil values' do + let(:args) { { email: nil, name: nil } } + + it 'does not normalize nil by default' do + expect(form.email).to be_nil + expect(form.name).to be_nil + end + end +end diff --git a/yaaf.gemspec b/yaaf.gemspec index 91ee8c6..032aebb 100644 --- a/yaaf.gemspec +++ b/yaaf.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.summary = 'Easing the form object pattern in Rails applications.' spec.homepage = 'https://github.com/rootstrap/yaaf' spec.license = 'MIT' - spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0') + spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = 'https://github.com/rootstrap/yaaf' @@ -21,8 +21,8 @@ Gem::Specification.new do |spec| spec.files = Dir['LICENSE.txt', 'README.md', 'lib/**/*'] spec.require_paths = ['lib'] - spec.add_dependency 'activemodel', '>= 5.2' - spec.add_dependency 'activerecord', '>= 5.2' + spec.add_dependency 'activemodel', '>= 7.1' + spec.add_dependency 'activerecord', '>= 7.1' spec.add_development_dependency 'database_cleaner-active_record', '~> 2.1.0' spec.add_development_dependency 'rake', '~> 13.0.1' From b8f12ff9b2a389450c70722c3f902d55a9d09e98 Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Fri, 30 Jan 2026 18:05:46 -0300 Subject: [PATCH 2/7] Add to readme. Remove codeclimate --- .github/workflows/ci.yml | 13 ------------- README.md | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd7e90e..140b063 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,22 +45,9 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby_version }} - - name: Before build - run: | - sudo apt-get install libsqlite3-dev - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter - ./cc-test-reporter before-build - env: - CC_TEST_REPORTER_ID: aff2c7b9e07e54d5fc9e5588d2e2a8bab4f69950d35000edc2b6250bbaba477d - name: Run test run: | bundle update bundle install --gemfile spec/gemfiles/${{ matrix.gemfile }} --jobs 4 --retry 3 bundle exec rake code_analysis bundle exec rspec - - name: Report to CodeClimate - run: | - ./cc-test-reporter after-build --exit-code 0 - env: - CC_TEST_REPORTER_ID: aff2c7b9e07e54d5fc9e5588d2e2a8bab4f69950d35000edc2b6250bbaba477d diff --git a/README.md b/README.md index 95806e0..dc6eac3 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ YAAF (Yet Another Active Form) is a gem that let you create form objects in an e We were going to name this gem `ActiveForm` to follow Rails naming conventions but given there are a lot of form object gems named like that we preferred to go with `YAAF`. ![CI](https://github.com/rootstrap/yaaf/workflows/CI/badge.svg) -[![Maintainability](https://api.codeclimate.com/v1/badges/c3dea064e1003b700260/maintainability)](https://codeclimate.com/github/rootstrap/yaaf/maintainability) -[![Test Coverage](https://api.codeclimate.com/v1/badges/c3dea064e1003b700260/test_coverage)](https://codeclimate.com/github/rootstrap/yaaf/test_coverage) ## Table of Contents @@ -23,6 +21,7 @@ We were going to name this gem `ActiveForm` to follow Rails naming conventions b - [#save!](#save!) - [Validations](#validations) - [Callbacks](#callbacks) + - [Normalizes](#normalizes) - [Sample app](#sample-app) - [Links](#links) - [Development](#development) @@ -249,6 +248,19 @@ Available callbacks are (listed in execution order): - `after_save` - `after_commit/after_rollback` +### Normalizes + +`YAAF` form objects support `normalizes` the same way as `ActiveModel` models. For example: + +```ruby +class RegistrationForm < YAAF::Form + normalizes :email, with: ->(email) { email.strip.downcase } + normalizes :name, with: ->(name) { name.strip.titleize } + + # ... +end +``` + ## Sample app You can find a sample app making use of the gem [here](https://yaaf-examples.herokuapp.com). Its code is also open source, and you can find it [here](https://github.com/rootstrap/yaaf-examples). From f0c9f96cf1181d8c76e0743a559e92d7d1e5a74f Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Fri, 30 Jan 2026 18:10:40 -0300 Subject: [PATCH 3/7] Fix --- lib/yaaf/form.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/yaaf/form.rb b/lib/yaaf/form.rb index b425503..c4aa69b 100644 --- a/lib/yaaf/form.rb +++ b/lib/yaaf/form.rb @@ -7,7 +7,8 @@ class Form include ::ActiveModel::Validations::Callbacks include ::ActiveRecord::Transactions include ::ActiveModel::Attributes - include ::ActiveModel::Attributes::Normalization + include ::ActiveModel::Attributes::Normalization if defined?(::ActiveModel::Attributes::Normalization) + include ::ActiveRecord::Normalization if defined?(::ActiveRecord::Normalization) define_model_callbacks :save From 09d69c6b5887a845445b460eaf4b12cb87505969 Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Fri, 30 Jan 2026 18:13:36 -0300 Subject: [PATCH 4/7] Fix --- .github/workflows/ci.yml | 2 ++ lib/yaaf/form.rb | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 140b063..d046ba0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,8 @@ jobs: ruby_version: '3.0' - gemfile: rails_main.gemfile ruby_version: '3.1' + - gemfile: rails_main.gemfile + ruby_version: '3.2' - gemfile: rails_8_1.gemfile ruby_version: '2.7' - gemfile: rails_8_1.gemfile diff --git a/lib/yaaf/form.rb b/lib/yaaf/form.rb index c4aa69b..2dacbcb 100644 --- a/lib/yaaf/form.rb +++ b/lib/yaaf/form.rb @@ -7,7 +7,11 @@ class Form include ::ActiveModel::Validations::Callbacks include ::ActiveRecord::Transactions include ::ActiveModel::Attributes - include ::ActiveModel::Attributes::Normalization if defined?(::ActiveModel::Attributes::Normalization) + + if defined?(::ActiveModel::Attributes::Normalization) + include ::ActiveModel::Attributes::Normalization + end + include ::ActiveRecord::Normalization if defined?(::ActiveRecord::Normalization) define_model_callbacks :save From ed4e19ad2827ca24e405d9effeab46955c643bc4 Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Mon, 2 Feb 2026 11:34:25 -0300 Subject: [PATCH 5/7] Fix --- .github/workflows/ci.yml | 90 ++++++++++++++++++++++- README.md | 2 +- lib/yaaf/form.rb | 4 +- spec/gemfiles/rails_5_2.gemfile | 6 ++ spec/gemfiles/rails_6_0.gemfile | 6 ++ spec/gemfiles/rails_6_1.gemfile | 6 ++ spec/gemfiles/rails_7_0.gemfile | 6 ++ spec/support/forms/with_normalize_form.rb | 22 +++--- spec/yaaf/normalization_spec.rb | 66 +++++++++-------- yaaf.gemspec | 6 +- 10 files changed, 163 insertions(+), 51 deletions(-) create mode 100644 spec/gemfiles/rails_5_2.gemfile create mode 100644 spec/gemfiles/rails_6_0.gemfile create mode 100644 spec/gemfiles/rails_6_1.gemfile create mode 100644 spec/gemfiles/rails_7_0.gemfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d046ba0..225c50d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,9 +12,17 @@ jobs: strategy: fail-fast: false matrix: - gemfile: [rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_8_1.gemfile, rails_main.gemfile] - ruby_version: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4', '4.0'] + gemfile: [rails_5_2.gemfile, rails_6_0.gemfile, rails_6_1.gemfile, rails_7_0.gemfile, rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_main.gemfile] + ruby_version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4'] exclude: + - gemfile: rails_main.gemfile + ruby_version: '2.3' + - gemfile: rails_main.gemfile + ruby_version: '2.4' + - gemfile: rails_main.gemfile + ruby_version: '2.5' + - gemfile: rails_main.gemfile + ruby_version: '2.6' - gemfile: rails_main.gemfile ruby_version: '2.7' - gemfile: rails_main.gemfile @@ -23,22 +31,100 @@ jobs: ruby_version: '3.1' - gemfile: rails_main.gemfile ruby_version: '3.2' + - gemfile: rails_8_1.gemfile + ruby_version: '2.3' + - gemfile: rails_8_1.gemfile + ruby_version: '2.4' + - gemfile: rails_8_1.gemfile + ruby_version: '2.5' + - gemfile: rails_8_1.gemfile + ruby_version: '2.6' - gemfile: rails_8_1.gemfile ruby_version: '2.7' - gemfile: rails_8_1.gemfile ruby_version: '3.0' - gemfile: rails_8_1.gemfile ruby_version: '3.1' + - gemfile: rails_8_0.gemfile + ruby_version: '2.3' + - gemfile: rails_8_0.gemfile + ruby_version: '2.4' + - gemfile: rails_8_0.gemfile + ruby_version: '2.5' + - gemfile: rails_8_0.gemfile + ruby_version: '2.6' - gemfile: rails_8_0.gemfile ruby_version: '2.7' - gemfile: rails_8_0.gemfile ruby_version: '3.0' - gemfile: rails_8_0.gemfile ruby_version: '3.1' + - gemfile: rails_7_2.gemfile + ruby_version: '2.3' + - gemfile: rails_7_2.gemfile + ruby_version: '2.4' + - gemfile: rails_7_2.gemfile + ruby_version: '2.5' + - gemfile: rails_7_2.gemfile + ruby_version: '2.6' - gemfile: rails_7_2.gemfile ruby_version: '2.7' - gemfile: rails_7_2.gemfile ruby_version: '3.0' + - gemfile: rails_7_1.gemfile + ruby_version: '2.3' + - gemfile: rails_7_1.gemfile + ruby_version: '2.4' + - gemfile: rails_7_1.gemfile + ruby_version: '2.5' + - gemfile: rails_7_1.gemfile + ruby_version: '2.6' + - gemfile: rails_7_0.gemfile + ruby_version: '2.3' + - gemfile: rails_7_0.gemfile + ruby_version: '2.4' + - gemfile: rails_7_0.gemfile + ruby_version: '2.5' + - gemfile: rails_7_0.gemfile + ruby_version: '2.6' + - gemfile: rails_7_0.gemfile + ruby_version: '3.4' + - gemfile: rails_6_1.gemfile + ruby_version: '2.3' + - gemfile: rails_6_1.gemfile + ruby_version: '2.4' + - gemfile: rails_6_1.gemfile + ruby_version: '3.1' + - gemfile: rails_6_1.gemfile + ruby_version: '3.2' + - gemfile: rails_6_1.gemfile + ruby_version: '3.3' + - gemfile: rails_6_1.gemfile + ruby_version: '3.4' + - gemfile: rails_6_0.gemfile + ruby_version: '2.3' + - gemfile: rails_6_0.gemfile + ruby_version: '2.4' + - gemfile: rails_6_0.gemfile + ruby_version: '3.0' + - gemfile: rails_6_0.gemfile + ruby_version: '3.1' + - gemfile: rails_6_0.gemfile + ruby_version: '3.2' + - gemfile: rails_6_0.gemfile + ruby_version: '3.3' + - gemfile: rails_6_0.gemfile + ruby_version: '3.4' + - gemfile: rails_5_2.gemfile + ruby_version: '3.0' + - gemfile: rails_5_2.gemfile + ruby_version: '3.1' + - gemfile: rails_5_2.gemfile + ruby_version: '3.2' + - gemfile: rails_5_2.gemfile + ruby_version: '3.3' + - gemfile: rails_5_2.gemfile + ruby_version: '3.4' env: BUNDLE_GEMFILE: spec/gemfiles/${{ matrix.gemfile }} steps: diff --git a/README.md b/README.md index dc6eac3..dbb91d7 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ Available callbacks are (listed in execution order): - `after_save` - `after_commit/after_rollback` -### Normalizes +### Normalizes (Rails 8.1+) `YAAF` form objects support `normalizes` the same way as `ActiveModel` models. For example: diff --git a/lib/yaaf/form.rb b/lib/yaaf/form.rb index 2dacbcb..b3cf10e 100644 --- a/lib/yaaf/form.rb +++ b/lib/yaaf/form.rb @@ -6,14 +6,12 @@ class Form include ::ActiveModel::Model include ::ActiveModel::Validations::Callbacks include ::ActiveRecord::Transactions - include ::ActiveModel::Attributes if defined?(::ActiveModel::Attributes::Normalization) + include ::ActiveModel::Attributes include ::ActiveModel::Attributes::Normalization end - include ::ActiveRecord::Normalization if defined?(::ActiveRecord::Normalization) - define_model_callbacks :save delegate :transaction, to: ::ActiveRecord::Base diff --git a/spec/gemfiles/rails_5_2.gemfile b/spec/gemfiles/rails_5_2.gemfile new file mode 100644 index 0000000..d869b89 --- /dev/null +++ b/spec/gemfiles/rails_5_2.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '../..' + +gem 'rails', '~> 5.2.0' +gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_6_0.gemfile b/spec/gemfiles/rails_6_0.gemfile new file mode 100644 index 0000000..d68315d --- /dev/null +++ b/spec/gemfiles/rails_6_0.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '../..' + +gem 'rails', '~> 6.0.0' +gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_6_1.gemfile b/spec/gemfiles/rails_6_1.gemfile new file mode 100644 index 0000000..617a8b0 --- /dev/null +++ b/spec/gemfiles/rails_6_1.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '../..' + +gem 'rails', '~> 6.1.0' +gem 'sqlite3', '~> 1.4.2' diff --git a/spec/gemfiles/rails_7_0.gemfile b/spec/gemfiles/rails_7_0.gemfile new file mode 100644 index 0000000..abce1b2 --- /dev/null +++ b/spec/gemfiles/rails_7_0.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec path: '../..' + +gem 'rails', '~> 7.0.0' +gem 'sqlite3', '~> 1.4.2' diff --git a/spec/support/forms/with_normalize_form.rb b/spec/support/forms/with_normalize_form.rb index 897b8f9..42b8658 100644 --- a/spec/support/forms/with_normalize_form.rb +++ b/spec/support/forms/with_normalize_form.rb @@ -1,17 +1,19 @@ class WithNormalizeForm < YAAF::Form - attribute :email, :string - attribute :name, :string + if defined?(ActiveModel::Attributes::Normalization) + attribute :email, :string + attribute :name, :string - normalizes :email, with: ->(email) { email.strip.downcase } - normalizes :name, with: ->(name) { name.strip.titleize } + normalizes :email, with: ->(email) { email.strip.downcase } + normalizes :name, with: ->(name) { name.strip.titleize } - def initialize(args) - super(args) + def initialize(args) + super(args) - @models = [user] - end + @models = [user] + end - def user - @user ||= User.new(email: email, name: name) + def user + @user ||= User.new(email: email, name: name) + end end end diff --git a/spec/yaaf/normalization_spec.rb b/spec/yaaf/normalization_spec.rb index dc9b5c9..c1e5b49 100644 --- a/spec/yaaf/normalization_spec.rb +++ b/spec/yaaf/normalization_spec.rb @@ -1,48 +1,50 @@ # frozen_string_literal: true RSpec.describe 'Form with normalization' do - let(:form) { WithNormalizeForm.new(args) } - let(:args) { { email: ' TEST@Example.com ', name: ' john doe ' } } - - describe 'attribute normalization' do - it 'normalizes email on assignment' do - expect(form.email).to eq('test@example.com') - end - - it 'normalizes name on assignment' do - expect(form.name).to eq('John Doe') + if defined?(ActiveModel::Attributes::Normalization) + let(:form) { WithNormalizeForm.new(args) } + let(:args) { { email: ' TEST@Example.com ', name: ' john doe ' } } + + describe 'attribute normalization' do + it 'normalizes email on assignment' do + expect(form.email).to eq('test@example.com') + end + + it 'normalizes name on assignment' do + expect(form.name).to eq('John Doe') + end end - end - describe '#save' do - subject { form.save } + describe '#save' do + subject { form.save } - it 'saves with normalized values' do - expect(subject).to be true - expect(User.last.email).to eq('test@example.com') - expect(User.last.name).to eq('John Doe') + it 'saves with normalized values' do + expect(subject).to be true + expect(User.last.email).to eq('test@example.com') + expect(User.last.name).to eq('John Doe') + end end - end - describe '#valid?' do - it 'validates with normalized values' do - expect(form.valid?).to be true + describe '#valid?' do + it 'validates with normalized values' do + expect(form.valid?).to be true + end end - end - context 'when updating attributes' do - it 'normalizes new values' do - form.email = ' test@example.com ' - expect(form.email).to eq('test@example.com') + context 'when updating attributes' do + it 'normalizes new values' do + form.email = ' test@example.com ' + expect(form.email).to eq('test@example.com') + end end - end - context 'with nil values' do - let(:args) { { email: nil, name: nil } } + context 'with nil values' do + let(:args) { { email: nil, name: nil } } - it 'does not normalize nil by default' do - expect(form.email).to be_nil - expect(form.name).to be_nil + it 'does not normalize nil by default' do + expect(form.email).to be_nil + expect(form.name).to be_nil + end end end end diff --git a/yaaf.gemspec b/yaaf.gemspec index 032aebb..91ee8c6 100644 --- a/yaaf.gemspec +++ b/yaaf.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.summary = 'Easing the form object pattern in Rails applications.' spec.homepage = 'https://github.com/rootstrap/yaaf' spec.license = 'MIT' - spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0') + spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0') spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = 'https://github.com/rootstrap/yaaf' @@ -21,8 +21,8 @@ Gem::Specification.new do |spec| spec.files = Dir['LICENSE.txt', 'README.md', 'lib/**/*'] spec.require_paths = ['lib'] - spec.add_dependency 'activemodel', '>= 7.1' - spec.add_dependency 'activerecord', '>= 7.1' + spec.add_dependency 'activemodel', '>= 5.2' + spec.add_dependency 'activerecord', '>= 5.2' spec.add_development_dependency 'database_cleaner-active_record', '~> 2.1.0' spec.add_development_dependency 'rake', '~> 13.0.1' From 459066fc10fee6ca785655240ce0b590111bc1d4 Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Mon, 2 Feb 2026 11:43:36 -0300 Subject: [PATCH 6/7] try fix --- spec/gemfiles/rails_main.gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/gemfiles/rails_main.gemfile b/spec/gemfiles/rails_main.gemfile index ff5fd7c..69b0059 100644 --- a/spec/gemfiles/rails_main.gemfile +++ b/spec/gemfiles/rails_main.gemfile @@ -3,3 +3,4 @@ source 'https://rubygems.org' gemspec path: '../..' gem 'rails', git: 'https://github.com/rails/rails', branch: 'main' +gem 'reek', '~> 6.0.5' From dc8ce60a1a8478a7f4048688b32ec6e154e765fa Mon Sep 17 00:00:00 2001 From: Andres Garcia Date: Mon, 2 Feb 2026 12:01:39 -0300 Subject: [PATCH 7/7] Remove reek gem --- .github/workflows/ci.yml | 2 +- Rakefile | 1 - spec/gemfiles/rails_main.gemfile | 1 - yaaf.gemspec | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 225c50d..11f9c81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - gemfile: [rails_5_2.gemfile, rails_6_0.gemfile, rails_6_1.gemfile, rails_7_0.gemfile, rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_main.gemfile] + gemfile: [rails_5_2.gemfile, rails_6_0.gemfile, rails_6_1.gemfile, rails_7_0.gemfile, rails_7_1.gemfile, rails_7_2.gemfile, rails_8_0.gemfile, rails_8_1.gemfile, rails_main.gemfile] ruby_version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', '3.4'] exclude: - gemfile: rails_main.gemfile diff --git a/Rakefile b/Rakefile index 07fa488..981c803 100644 --- a/Rakefile +++ b/Rakefile @@ -2,5 +2,4 @@ task :code_analysis do sh 'bundle exec rubocop lib spec' - sh 'bundle exec reek lib' end diff --git a/spec/gemfiles/rails_main.gemfile b/spec/gemfiles/rails_main.gemfile index 69b0059..ff5fd7c 100644 --- a/spec/gemfiles/rails_main.gemfile +++ b/spec/gemfiles/rails_main.gemfile @@ -3,4 +3,3 @@ source 'https://rubygems.org' gemspec path: '../..' gem 'rails', git: 'https://github.com/rails/rails', branch: 'main' -gem 'reek', '~> 6.0.5' diff --git a/yaaf.gemspec b/yaaf.gemspec index 91ee8c6..bdbaea7 100644 --- a/yaaf.gemspec +++ b/yaaf.gemspec @@ -26,7 +26,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'database_cleaner-active_record', '~> 2.1.0' spec.add_development_dependency 'rake', '~> 13.0.1' - spec.add_development_dependency 'reek', '~> 5.6.0' spec.add_development_dependency 'rspec', '~> 3.9.0' spec.add_development_dependency 'rubocop', '~> 0.80.0' spec.add_development_dependency 'simplecov', '~> 0.17.1'