From 658492239d2955ac4dd0c3762d7c0add21e02830 Mon Sep 17 00:00:00 2001 From: dannysperry Date: Sat, 10 Jan 2015 13:28:34 -0800 Subject: [PATCH 1/3] added original value to uniqueness validations and checked against that on validations --- app/assets/javascripts/judge.js | 26 ++++++++++++------- lib/judge/controller.rb | 5 ++-- lib/judge/validation.rb | 3 ++- lib/judge/validator.rb | 7 +++-- .../judge/validations_controller_spec.rb | 16 +++++++++--- spec/javascripts/judge-spec.js | 3 ++- 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/judge.js b/app/assets/javascripts/judge.js index fab3891..985a8a0 100644 --- a/app/assets/javascripts/judge.js +++ b/app/assets/javascripts/judge.js @@ -136,6 +136,11 @@ return $1.toUpperCase().replace('_',''); }); }; + originalValue = function(el) { + var validations = JSON.parse(el.getAttribute('data-validate')); + var validation = _.filter(validations, function (validation) { return validation.kind == "uniqueness"})[0]; + return validation.original_value; + }; // Build the URL necessary to send a GET request to the mounted validations // controller to check the validity of the given form element. @@ -147,6 +152,9 @@ 'value' : el.value, 'kind' : kind }; + if (kind == 'uniqueness') { + params['original_value'] = originalValue(el); + } return path + queryString(params); }; @@ -265,7 +273,7 @@ presence: function(options, messages) { return closed(this.value.length ? [] : [messages.blank]); }, - + // ActiveModel::Validations::LengthValidator length: function(options, messages) { var msgs = [], @@ -282,7 +290,7 @@ }, this); return closed(msgs); }, - + // ActiveModel::Validations::ExclusionValidator exclusion: function(options, messages) { var stringIn = _(options['in']).map(function(o) { @@ -292,7 +300,7 @@ _.include(stringIn, this.value) ? [messages.exclusion] : [] ); }, - + // ActiveModel::Validations::InclusionValidator inclusion: function(options, messages) { var stringIn = _(options['in']).map(function(o) { @@ -302,7 +310,7 @@ !_.include(stringIn, this.value) ? [messages.inclusion] : [] ); }, - + // ActiveModel::Validations::NumericalityValidator numericality: function(options, messages) { var operators = { @@ -313,7 +321,7 @@ less_than_or_equal_to: '<=' }, msgs = [], - parsedValue = parseFloat(this.value, 10); + parsedValue = parseFloat(this.value, 10); if (isNaN(Number(this.value))) { msgs.push(messages.not_a_number); @@ -330,7 +338,7 @@ } return closed(msgs); }, - + // ActiveModel::Validations::FormatValidator format: function(options, messages) { var msgs = []; @@ -348,12 +356,12 @@ } return closed(msgs); }, - + // ActiveModel::Validations::AcceptanceValidator acceptance: function(options, messages) { return closed(this.checked === true ? [] : [messages.accepted]); }, - + // ActiveModel::Validations::ConfirmationValidator confirmation: function(options, messages) { var id = this.getAttribute('id'), @@ -366,7 +374,7 @@ // ActiveModel::Validations::UniquenessValidator uniqueness: function(options, messages) { - var validation = pending(); + var validation = pending(); get(urlFor(this, 'uniqueness'), { success: function(status, headers, text) { validation.close(text); diff --git a/lib/judge/controller.rb b/lib/judge/controller.rb index 8e555be..f82439f 100644 --- a/lib/judge/controller.rb +++ b/lib/judge/controller.rb @@ -14,7 +14,7 @@ def validation(params) private - REQUIRED_PARAMS = %w{klass attribute value kind} + REQUIRED_PARAMS = %w{klass attribute value kind original_value} def params_exposed?(params) Judge.config.exposed?(params[:klass], params[:attribute]) @@ -25,11 +25,12 @@ def params_present?(params) end def normalized_params(params) - params = params.dup.keep_if { |k| REQUIRED_PARAMS.include?(k) } + params = params.dup.keep_if {|k| REQUIRED_PARAMS.include?(k) || (k == :original_value && params[:kind] == :uniqueness)} params[:klass] = find_klass(params[:klass]) if params[:klass] params[:attribute] = params[:attribute].to_sym if params[:attribute] params[:value] = URI.decode(params[:value]) if params[:value] params[:kind] = params[:kind].to_sym if params[:kind] + params[:original_value] = URI.decode(params[:original_value]) if params[:original_value] params end diff --git a/lib/judge/validation.rb b/lib/judge/validation.rb index d3f6eb1..4899860 100644 --- a/lib/judge/validation.rb +++ b/lib/judge/validation.rb @@ -6,6 +6,7 @@ def initialize(params) @attribute = params[:attribute] @value = params[:value] @kind = params[:kind] + @original_value = params[:original_value] validate! end @@ -27,7 +28,7 @@ def record def validate! record.errors.delete(@attribute) - amv.validate_each(record, @attribute, @value) + amv.validate_each(record, @attribute, @value) unless amv.kind == :uniqueness && @value == @original_value && @original_value != "" self end diff --git a/lib/judge/validator.rb b/lib/judge/validator.rb index d01253b..bbe1a2c 100644 --- a/lib/judge/validator.rb +++ b/lib/judge/validator.rb @@ -2,7 +2,7 @@ module Judge class Validator - attr_reader :active_model_validator, :kind, :options, :method, :messages + attr_reader :active_model_validator, :kind, :options, :method, :messages, :original_value REJECTED_OPTIONS = [:if, :on, :unless, :tokenizer, :scope, :case_sensitive, :judge] @@ -11,14 +11,17 @@ def initialize(object, method, amv) @options = amv.options.reject { |key| REJECTED_OPTIONS.include?(key) } @method = method @messages = Judge::MessageCollection.new(object, method, amv) + @original_value = object.send(method) end def to_hash - { + params = { :kind => kind, :options => options, :messages => messages.to_hash } + params[:original_value] = original_value if kind == :uniqueness + params end end diff --git a/spec/controllers/judge/validations_controller_spec.rb b/spec/controllers/judge/validations_controller_spec.rb index 07fdff0..3418fed 100644 --- a/spec/controllers/judge/validations_controller_spec.rb +++ b/spec/controllers/judge/validations_controller_spec.rb @@ -5,15 +5,16 @@ let(:headers) do { :accept => "application/json" } end - + let(:valid_params) do { :use_route => :judge, :format => :json, :klass => "User", :attribute => "username", - :value => "invisibleman", - :kind => "uniqueness" + :value => "tinbucktwo", + :kind => "uniqueness", + :original_value => "tinbucktwo" } end @@ -24,7 +25,8 @@ :klass => "User", :attribute => "city", :value => "", - :kind => "city" + :kind => "city", + :original_value => "nil" } end @@ -36,6 +38,12 @@ response.should be_success response.body.should eql "[]" end + it "responds with empty JSON array if original_value equals the value" do + FactoryGirl.create(:user, username: 'tinbucktwo') + get :build, valid_params, headers + response.should be_success + response.body.should eql "[]" + end it "responds with JSON array of error messages if invalid" do get :build, invalid_params, headers response.should be_success diff --git a/spec/javascripts/judge-spec.js b/spec/javascripts/judge-spec.js index aa49507..103b14d 100644 --- a/spec/javascripts/judge-spec.js +++ b/spec/javascripts/judge-spec.js @@ -446,6 +446,7 @@ describe('judge', function() { validator = _.bind(judge.eachValidators.uniqueness, el); el.value = 'leader@team.com'; el.name = 'team[leader][email]'; + el.setAttribute('data-validate', '[{"kind":"uniqueness","options":{},"messages":{},"original_value":"leader"}]') }); it('returns a pending Validation', function() { validation = validator({}, {}); @@ -460,7 +461,7 @@ describe('judge', function() { server.respond(); }); runs(function() { - expect(server.requests[0].url).toBe('/judge?klass=Leader&attribute=email&value=leader%40team.com&kind=uniqueness'); + expect(server.requests[0].url).toBe('/judge?klass=Leader&attribute=email&value=leader%40team.com&kind=uniqueness&original_value=leader'); }); }); it('closes Validation as valid if the server responds with an empty JSON array', function() { From c780e3311488985ff214152f9df75bebe7a09f82 Mon Sep 17 00:00:00 2001 From: dannysperry Date: Sun, 11 Jan 2015 12:03:19 -0800 Subject: [PATCH 2/3] fixes #38 - updated judge spec to use the uniqueAttr stringified hash --- spec/javascripts/judge-spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/javascripts/judge-spec.js b/spec/javascripts/judge-spec.js index 103b14d..7a37ee4 100644 --- a/spec/javascripts/judge-spec.js +++ b/spec/javascripts/judge-spec.js @@ -1,8 +1,8 @@ describe('judge', function() { var server, - uniquenessAttr = '[{"kind":"uniqueness","options":{},"messages":{}}]', + uniquenessAttr = '[{"kind":"uniqueness","options":{},"messages":{},"original_value":"leader"}]', presenceAttr = '[{"kind":"presence","options":{},"messages":{"blank":"must not be blank"}}]', - uniqPresenceAttr = '[{"kind":"uniqueness","options":{},"messages":{}},{"kind":"presence","options":{},"messages":{"blank":"must not be blank"}}]', + uniqPresenceAttr = '[{"kind":"uniqueness","options":{},"messages":{},"original_value":"leader"},{"kind":"presence","options":{},"messages":{"blank":"must not be blank"}}]', mixedAttr = '[{"kind":"presence","options":{},"messages":{"blank":"must not be blank"}},{"kind":"inclusion","options":{"in":["a","b"]},"messages":{"inclusion":"must be a or b"}}]', uniqAndIncAttr = '[{"kind":"uniqueness","options":{},"messages":{}},{"kind":"inclusion","options":{"in":["a","b"]},"messages":{"inclusion":"must be a or b"}}]'; @@ -446,7 +446,7 @@ describe('judge', function() { validator = _.bind(judge.eachValidators.uniqueness, el); el.value = 'leader@team.com'; el.name = 'team[leader][email]'; - el.setAttribute('data-validate', '[{"kind":"uniqueness","options":{},"messages":{},"original_value":"leader"}]') + el.setAttribute('data-validate', uniquenessAttr) }); it('returns a pending Validation', function() { validation = validator({}, {}); From 16257977752b3076704474e6b168a97723ea6851 Mon Sep 17 00:00:00 2001 From: dannysperry Date: Mon, 12 Jan 2015 12:56:39 -0800 Subject: [PATCH 3/3] updated generaic equality to type equality in judge.js --- app/assets/javascripts/judge.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/judge.js b/app/assets/javascripts/judge.js index 985a8a0..a664135 100644 --- a/app/assets/javascripts/judge.js +++ b/app/assets/javascripts/judge.js @@ -138,7 +138,7 @@ }; originalValue = function(el) { var validations = JSON.parse(el.getAttribute('data-validate')); - var validation = _.filter(validations, function (validation) { return validation.kind == "uniqueness"})[0]; + var validation = _.filter(validations, function (validation) { return validation.kind === "uniqueness"})[0]; return validation.original_value; }; @@ -152,7 +152,7 @@ 'value' : el.value, 'kind' : kind }; - if (kind == 'uniqueness') { + if (kind === 'uniqueness') { params['original_value'] = originalValue(el); } return path + queryString(params);