Skip to content

Commit

Permalink
Add Rails 8.0 compatibility (#952)
Browse files Browse the repository at this point in the history
- Add class parameter to Uniqueness validator as per rails/rails#53598
- Test new edge methods textarea and checkbox
- Allow new Rails 8 helper names like `textarea` (close #941)
  • Loading branch information
tagliala authored Nov 12, 2024
1 parent 135f0a3 commit 97fde95
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 30 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
gemfile: [rails_6.1, rails_7.0, rails_7.1, rails_7.2]
gemfile: [rails_6.1, rails_7.0, rails_7.1, rails_7.2, rails_8.0]
channel: ['stable']

include:
Expand All @@ -32,15 +32,24 @@ jobs:
- ruby-version: 'head'
gemfile: rails_7.2
channel: 'experimental'
- ruby-version: 'head'
gemfile: rails_8.0
channel: 'experimental'
- ruby-version: 'head'
gemfile: rails_edge
channel: 'experimental'

exclude:
- ruby-version: '2.7'
gemfile: rails_7.2
- ruby-version: '2.7'
gemfile: rails_8.0
- ruby-version: '3.0'
gemfile: rails_7.2
- ruby-version: '3.0'
gemfile: rails_8.0
- ruby-version: '3.1'
gemfile: rails_8.0
- ruby-version: '3.2'
gemfile: rails_6.1
- ruby-version: '3.3'
Expand Down
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Metrics/MethodLength:
- 'test/**/*'

Metrics/ModuleLength:
Max: 101
Max: 109
Exclude:
- 'test/**/*'

Expand Down
5 changes: 4 additions & 1 deletion Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ end

appraise 'rails-7.1' do
gem 'rails', '~> 7.1.0'
gem 'sqlite3', '~> 1.7' # FIXME: remove after rails/rails#51592
end

appraise 'rails-7.2' do
gem 'rails', '~> 7.2.0'
end

appraise 'rails-8.0' do
gem 'rails', '~> 8.0.0'
end

appraise 'rails-edge' do
gem 'rails', git: 'https://github.com/rails/rails.git', branch: 'main'
end
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Changelog

## main / unreleased
## 22.3.0 / 2024-11-08

* [FEATURE] Rails 8.0 compatibility
* [ENHANCEMENT] Update QUnit to 2.22.0
* [ENHANCEMENT] Prefer `require_relative` for internal requires

## 22.2.0 / 2026-06-01
## 22.2.0 / 2024-06-01

* [FEATURE] Allow Rails 8.0 alpha
* [ENHANCEMENT] Test against Ruby 3.3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![Coverage Status](https://coveralls.io/repos/github/DavyJonesLocker/client_side_validations/badge.svg?branch=main)](https://coveralls.io/github/DavyJonesLocker/client_side_validations?branch=main)


`ClientSideValidations` made easy for your Rails 6.1 / 7.x applications!
`ClientSideValidations` made easy for your Rails 6.1, 7.x, and 8.0 applications!

## Project Goals ##

Expand Down
4 changes: 2 additions & 2 deletions client_side_validations.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
spec.email = ['[email protected]', '[email protected]']

spec.summary = 'Client Side Validations'
spec.description = 'Client Side Validations made easy for your Rails 6.1 and 7.x applications'
spec.description = 'Client Side Validations made easy for your Rails 6.1, 7.x, and 8.0 applications'
spec.homepage = 'https://github.com/DavyJonesLocker/client_side_validations'
spec.license = 'MIT'

Expand All @@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = '>= 2.7'

spec.add_dependency 'js_regex', '~> 3.7'
spec.add_dependency 'rails', '>= 6.1', '< 8.0'
spec.add_dependency 'rails', '>= 6.1'
end
2 changes: 1 addition & 1 deletion gemfiles/rails_7.1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ gem "shotgun"
gem "simplecov"
gem "simplecov-lcov"
gem "sinatra"
gem "sqlite3", "~> 1.7"
gem "sqlite3"
gem "webrick"
gem "rails", "~> 7.1.0"

Expand Down
25 changes: 25 additions & 0 deletions gemfiles/rails_8.0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "appraisal"
gem "byebug"
gem "m"
gem "minitest"
gem "mocha"
gem "rake"
gem "rubocop"
gem "rubocop-minitest"
gem "rubocop-packaging"
gem "rubocop-performance"
gem "rubocop-rails"
gem "rubocop-rake"
gem "shotgun"
gem "simplecov"
gem "simplecov-lcov"
gem "sinatra"
gem "sqlite3"
gem "webrick"
gem "rails", "~> 8.0.0"

gemspec path: "../"
13 changes: 12 additions & 1 deletion lib/client_side_validations/action_view/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ module ActionView
module Helpers
module FormBuilder
def self.prepended(base)
(base.field_helpers - %i[label check_box radio_button fields_for fields hidden_field file_field]).each do |selector|
selectors = base.field_helpers - %i[label check_box checkbox radio_button fields_for fields hidden_field file_field]

selectors.each do |selector|
base.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
# Cannot call super here, rewrite all
def #{selector}(method, options = {}) # def text_field(method, options = {})
Expand All @@ -19,6 +21,10 @@ def #{selector}(method, options = {}) # def text_field(method, options = {
end # end
RUBY_EVAL
end

base.class_eval do
alias_method :text_area, :textarea if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:textarea)
end
end

def initialize(object_name, object, template, options)
Expand Down Expand Up @@ -47,6 +53,7 @@ def check_box(method, options = {}, checked_value = '1', unchecked_value = '0')
options.delete(:validate)
super
end
alias checkbox check_box if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:checkbox)

%i[collection_check_boxes collection_radio_buttons].each do |method_name|
define_method method_name do |method, collection, value_method, text_method, options = {}, html_options = {}, &block|
Expand All @@ -56,6 +63,10 @@ def check_box(method, options = {}, checked_value = '1', unchecked_value = '0')
end
end

if ::ActionView::Helpers::FormBuilder.public_instance_methods.include?(:collection_checkboxes)
alias collection_checkboxes collection_check_boxes
end

def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
build_validation_options(method, html_options.merge(name: options[:name]))
html_options.delete(:validate)
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@client-side-validations/client-side-validations",
"description": "Client Side Validations made easy for your Rails 6.1 / 7.x applications",
"description": "Client Side Validations made easy for your Rails 6.1, 7.x, and 8.0 applications",
"repository": {
"type": "git",
"url": "git+https://github.com/DavyJonesLocker/client_side_validations.git"
Expand All @@ -22,15 +22,15 @@
"test": "test/javascript/run-qunit.mjs"
},
"devDependencies": {
"@babel/core": "^7.25.8",
"@babel/preset-env": "^7.25.8",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-node-resolve": "^15.3.0",
"chrome-launcher": "^1.1.2",
"eslint": "^9.12.0",
"neostandard": "^0.11.6",
"puppeteer-core": "^23.5.3",
"rollup": "^4.24.0",
"eslint": "^9.14.0",
"neostandard": "^0.11.7",
"puppeteer-core": "^23.7.1",
"rollup": "^4.25.0",
"rollup-plugin-copy": "^3.5.0"
},
"peerDependencies": {
Expand Down
46 changes: 46 additions & 0 deletions test/action_view/cases/test_form_for_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ def test_text_area
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:textarea)
def test_textarea
form_for(@post, validate: true) do |f|
concat f.textarea(:cost)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do
form_field('textarea', id: 'post_cost', name: 'post[cost]', tag_content: "\n")
end

assert_dom_equal expected, output_buffer
end
end

def test_file_field
form_for(@post, validate: true) do |f|
concat f.file_field(:cost)
Expand Down Expand Up @@ -97,6 +112,22 @@ def test_check_box
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:checkbox)
def test_checkbox
form_for(@post, validate: true) do |f|
concat f.checkbox(:cost)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do
form_field('input', name: 'post[cost]', type: 'hidden', value: '0') +
form_field('input', id: 'post_cost', name: 'post[cost]', type: 'checkbox', value: '1')
end

assert_dom_equal expected, output_buffer
end
end

def test_check_box_ensure_no_validate_attribute
form_for(@post, validate: true) do |f|
concat f.check_box(:cost, validate: true)
Expand Down Expand Up @@ -425,6 +456,21 @@ def test_collection_check_boxes
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.public_instance_methods.include?(:collection_checkboxes)
def test_collection_checkboxes
form_for(@post, validate: true) do |f|
concat f.collection_checkboxes(:cost, [], :id, :name)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_for('/posts', 'new_post', 'new_post', validators: validators) do
form_field('input', name: 'post[cost][]', type: 'hidden', value: '')
end

assert_dom_equal expected, output_buffer
end
end

def test_collection_check_boxes_with_validate_options
form_for(@post, validate: true) do |f|
concat f.collection_check_boxes(:cost, [], :id, :name, {}, validate: false)
Expand Down
46 changes: 46 additions & 0 deletions test/action_view/cases/test_form_with_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ def test_form_with_text_area
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:textarea)
def test_form_with_textarea
form_with(model: @post, validate: true) do |f|
concat f.textarea(:cost)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_with('/posts', validators: validators) do
form_field('textarea', id: 'post_cost', name: 'post[cost]', tag_content: "\n")
end

assert_dom_equal expected, output_buffer
end
end

def test_form_with_file_field
form_with(model: @post, validate: true) do |f|
concat f.file_field(:cost)
Expand Down Expand Up @@ -122,6 +137,22 @@ def test_form_with_check_box
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:checkbox)
def test_form_with_checkbox
form_with(model: @post, validate: true) do |f|
concat f.checkbox(:cost)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_with('/posts', validators: validators) do
form_field('input', name: 'post[cost]', type: 'hidden', value: '0') +
form_field('input', id: 'post_cost', name: 'post[cost]', type: 'checkbox', value: '1')
end

assert_dom_equal expected, output_buffer
end
end

def test_form_with_check_box_ensure_no_validate_attribute
form_with(model: @post, validate: true) do |f|
concat f.check_box(:cost, validate: true)
Expand Down Expand Up @@ -440,6 +471,21 @@ def test_form_with_collection_check_boxes
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.public_instance_methods.include?(:collection_checkboxes)
def test_form_with_collection_checkboxes
form_with(model: @post, validate: true) do |f|
concat f.collection_checkboxes(:cost, [], :id, :name)
end

validators = { 'post[cost]' => { presence: [{ message: I18n.t('errors.messages.blank') }] } }
expected = whole_form_with('/posts', validators: validators) do
form_field('input', name: 'post[cost][]', type: 'hidden', value: '')
end

assert_dom_equal expected, output_buffer
end
end

def test_form_with_collection_check_boxes_with_validate_options
form_with(model: @post, validate: true) do |f|
concat f.collection_check_boxes(:cost, [], :id, :name, {}, validate: false)
Expand Down
29 changes: 29 additions & 0 deletions test/action_view/cases/test_legacy_form_for_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ def test_text_area
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:textarea)
def test_textarea
form_for(@post) do |f|
concat f.textarea(:cost)
end

expected = whole_form_for('/posts', 'new_post', 'new_post') do
form_field('textarea', id: 'post_cost', name: 'post[cost]', tag_content: "\n")
end

assert_dom_equal expected, output_buffer
end
end

def test_file_field
form_for(@post) do |f|
concat f.file_field(:cost)
Expand All @@ -57,6 +71,21 @@ def test_check_box
assert_dom_equal expected, output_buffer
end

if ::ActionView::Helpers::FormBuilder.field_helpers.include?(:checkbox)
def test_checkbox
form_for(@post) do |f|
concat f.checkbox(:cost)
end

expected = whole_form_for('/posts', 'new_post', 'new_post') do
hidden_input_for_checkbox('post[cost]') +
form_field('input', id: 'post_cost', name: 'post[cost]', type: 'checkbox', value: '1')
end

assert_dom_equal expected, output_buffer
end
end

def test_radio_button
form_for(@post) do |f|
concat f.radio_button(:cost, '10')
Expand Down
Loading

0 comments on commit 97fde95

Please sign in to comment.