Skip to content

Commit

Permalink
Merge branch 'rails-6-beta-2'
Browse files Browse the repository at this point in the history
* rails-6-beta-2:
  Support javascript case-sensitive uniqueness
  Fix uniqueness validator behavior
  Add support to Rails 6.0.0.beta2
  • Loading branch information
tagliala committed Feb 28, 2019
2 parents 04d9e13 + 645b8b0 commit 2782324
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 23 deletions.
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ gemfile:
- gemfiles/rails_5.0.gemfile
- gemfiles/rails_5.1.gemfile
- gemfiles/rails_5.2.gemfile
- gemfiles/rails_6.0.0.beta1.gemfile
- gemfiles/rails_6.0.0.beta2.gemfile
- gemfiles/rails_edge.gemfile
matrix:
allow_failures:
- rvm: ruby-head
- gemfile: gemfiles/rails_edge.gemfile
exclude:
- rvm: 2.2.10
gemfile: gemfiles/rails_6.0.0.beta1.gemfile
gemfile: gemfiles/rails_6.0.0.beta2.gemfile
- rvm: 2.2.10
gemfile: gemfiles/rails_edge.gemfile
- rvm: 2.3.8
gemfile: gemfiles/rails_6.0.0.beta1.gemfile
gemfile: gemfiles/rails_6.0.0.beta2.gemfile
- rvm: 2.3.8
gemfile: gemfiles/rails_edge.gemfile
- rvm: 2.4.5
gemfile: gemfiles/rails_6.0.0.beta1.gemfile
gemfile: gemfiles/rails_6.0.0.beta2.gemfile
- rvm: 2.4.5
gemfile: gemfiles/rails_edge.gemfile
fast_finish: true
4 changes: 2 additions & 2 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ appraise 'rails-5.2' do
gem 'rails', '~> 5.2.0'
end

appraise 'rails-6.0.0.beta1' do
gem 'rails', '~> 6.0.0.beta1'
appraise 'rails-6.0.0.beta2' do
gem 'rails', '~> 6.0.0.beta2'
end

appraise 'rails-edge' do
Expand Down
2 changes: 1 addition & 1 deletion client_side_validations.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
spec.files = `git ls-files -z -- {CHANGELOG.md,LICENSE.md,README.md,lib,vendor}`.split("\x0")
spec.require_paths = ['lib']

spec.add_dependency 'rails', '>= 5.0.0.1', '<= 6.0.0.beta1'
spec.add_dependency 'rails', '>= 5.0.0.1', '<= 6.0.0.beta2'

spec.add_dependency 'jquery-rails', '~> 4.3'
spec.add_dependency 'js_regex', '~> 3.1'
Expand Down
8 changes: 7 additions & 1 deletion coffeescript/rails.validations.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,14 @@ ClientSideValidations =
valid = true

form.find(":input[name^=\"#{name_prefix}\"][name$=\"#{name_suffix}\"]").each ->
other_value = $(@).val()

unless options.case_sensitive
value = value.toLowerCase()
other_value = other_value.toLowerCase()

if $(@).attr('name') != name
if $(@).val() == value
if other_value == value
valid = false
$(@).data('notLocallyUnique', true)
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

source 'https://rubygems.org'

gem 'rails', '~> 6.0.0.beta1'
gem 'rails', '~> 6.0.0.beta2'

gemspec path: '../'
2 changes: 1 addition & 1 deletion lib/client_side_validations/active_record/uniqueness.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Uniqueness
def client_side_hash(model, attribute, _force = nil)
hash = {}
hash[:message] = model.errors.generate_message(attribute, message_type, options.except(:scope))
hash[:case_sensitive] = options[:case_sensitive]
hash[:case_sensitive] = true if options[:case_sensitive]
hash[:id] = model.id unless model.new_record?
hash[:allow_blank] = true if options[:allow_nil] || options[:allow_blank]

Expand Down
38 changes: 28 additions & 10 deletions test/active_record/cases/test_uniqueness_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,82 @@

module ActiveRecord
class UniquenessValidatorTest < ClientSideValidations::ActiveRecordTestBase
def uniqueness_validator_options(hash)
if defined?(Rails.version) && Gem::Version.new(Rails.version) < Gem::Version.new('6.0.0.beta2')
{ case_sensitive: true }.merge(hash)
else
hash
end
end

def test_uniqueness_client_side_hash
expected_hash = { message: 'has already been taken', case_sensitive: true }
expected_hash = uniqueness_validator_options(message: 'has already been taken')
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name]).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_allowing_blank
expected_hash = { message: 'has already been taken', case_sensitive: true, allow_blank: true }
expected_hash = uniqueness_validator_options(message: 'has already been taken', allow_blank: true)
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], allow_blank: true).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_allowing_nil
expected_hash = { message: 'has already been taken', case_sensitive: true, allow_blank: true }
expected_hash = uniqueness_validator_options(message: 'has already been taken', allow_blank: true)
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], allow_nil: true).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_case_insensitive
expected_hash = { message: 'has already been taken' }
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], case_sensitive: false).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_case_sensitive
expected_hash = uniqueness_validator_options(message: 'has already been taken', case_sensitive: true)
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], case_sensitive: true).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_with_custom_message
expected_hash = { message: 'is not available', case_sensitive: true }
expected_hash = uniqueness_validator_options(message: 'is not available')
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], message: 'is not available').client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_with_existing_record
@user.stubs(:new_record?).returns(false)
@user.stubs(:id).returns(1)
expected_hash = { message: 'has already been taken', case_sensitive: true, id: 1 }
expected_hash = uniqueness_validator_options(message: 'has already been taken', id: 1)
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name]).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_with_single_scope_item
@user.stubs(:age).returns(30)
@user.stubs(:title).returns('test title')
expected_hash = { message: 'has already been taken', case_sensitive: true, scope: { title: 'test title' } }
expected_hash = uniqueness_validator_options(message: 'has already been taken', scope: { title: 'test title' })
result_hash = UniquenessValidator.new(attributes: [:name], scope: :title).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end

def test_uniqueness_client_side_hash_with_multiple_scope_items
@user.stubs(:age).returns(30)
@user.stubs(:title).returns('test title')
expected_hash = { message: 'has already been taken', case_sensitive: true, scope: { age: 30, title: 'test title' } }
expected_hash = uniqueness_validator_options(message: 'has already been taken', scope: { age: 30, title: 'test title' })
result_hash = UniquenessValidator.new(attributes: [:name], scope: %i[age title]).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end

def test_uniqueness_client_side_hash_with_empty_scope_array
expected_hash = { message: 'has already been taken', case_sensitive: true }
expected_hash = uniqueness_validator_options(message: 'has already been taken')
result_hash = UniquenessValidator.new(attributes: [:name], scope: []).client_side_hash(@user, :name)
assert_equal expected_hash, result_hash
end

def test_uniqueness_client_side_hash_when_nested_module
@user = ActiveRecordTestModule::User2.new
expected_hash = { message: 'has already been taken', case_sensitive: true, class: 'active_record_test_module/user2' }
expected_hash = uniqueness_validator_options(message: 'has already been taken', class: 'active_record_test_module/user2')
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name]).client_side_hash(@user, :name)
end

def test_uniqueness_client_side_hash_with_class_from_options
@user = UserForm.new
expected_hash = { message: 'has already been taken', case_sensitive: true, class: 'user' }
expected_hash = uniqueness_validator_options(message: 'has already been taken', class: 'user')
assert_equal expected_hash, UniquenessValidator.new(attributes: [:name], client_validations: { class: 'User' }).client_side_hash(@user, :name)
end
end
Expand Down
43 changes: 41 additions & 2 deletions test/javascript/public/test/validators/uniqueness.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ QUnit.module('Uniqueness options', {
}
});

QUnit.test('when matching local uniqueness for nested has-many resources', function(assert) {
QUnit.test('when matching local case-insensitive uniqueness for nested has-many resources', function(assert) {
dataCsv = {
html_settings: {
type: 'ActionView::Helpers::FormBuilder',
Expand Down Expand Up @@ -67,7 +67,46 @@ QUnit.test('when matching local uniqueness for nested has-many resources', funct
options = { 'message': "must be unique" };

user_0_email.val('not-locally-unique');
user_1_email.val('not-locally-unique');
user_1_email.val('Not-Locally-Unique');

assert.equal(ClientSideValidations.validators.local.uniqueness(user_1_email, options), "must be unique");
});

QUnit.test('when matching case-sensitive local uniqueness for nested has-many resources', function(assert) {
dataCsv = {
html_settings: {
type: 'ActionView::Helpers::FormBuilder',
input_tag: '<div class="field_with_errors"><span id="input_tag" /><label for="user_name" class="message"></label></div>',
label_tag: '<div class="field_with_errors"><label id="label_tag" /></div>'
},
validators: { 'user[email]':{"uniqueness":[{"message": "must be unique"}]}}
}

$('#qunit-fixture')
.append($('<form />', {
action: '/users',
'data-client-side-validations': JSON.stringify(dataCsv),
method: 'post',
id: 'new_user_3'
}))
.find('form')
.append($('<input />', {
name: 'profile[user_attributes][0][email]',
id: 'user_0_email',
}))
.append($('<input />', {
name: 'profile[user_attributes][1][email]',
id: 'user_1_email',
}));

$('form#new_user_3').validate();

var user_0_email = $('#user_0_email'),
user_1_email = $('#user_1_email'),
options = { 'message': "must be unique", "case_sensitive": true };

user_0_email.val('locally-unique');
user_1_email.val('Locally-Unique');

assert.equal(ClientSideValidations.validators.local.uniqueness(user_1_email, options), undefined);
});
8 changes: 7 additions & 1 deletion vendor/assets/javascripts/rails.validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,14 @@
form = element.closest('form');
valid = true;
form.find(":input[name^=\"" + name_prefix + "\"][name$=\"" + name_suffix + "\"]").each(function() {
var other_value;
other_value = $(this).val();
if (!options.case_sensitive) {
value = value.toLowerCase();
other_value = other_value.toLowerCase();
}
if ($(this).attr('name') !== name) {
if ($(this).val() === value) {
if (other_value === value) {
valid = false;
return $(this).data('notLocallyUnique', true);
} else {
Expand Down

0 comments on commit 2782324

Please sign in to comment.