├── .rvmrc ├── .gitignore ├── lib ├── client_side_validations │ ├── version.rb │ ├── core_ext.rb │ ├── active_model │ │ ├── format.rb │ │ ├── presence.rb │ │ ├── acceptance.rb │ │ ├── exclusion.rb │ │ ├── inclusion.rb │ │ ├── length.rb │ │ └── numericality.rb │ ├── core_ext │ │ ├── range.rb │ │ └── regexp.rb │ ├── mongoid.rb │ ├── action_view │ │ ├── form_tag_helper.rb │ │ ├── form_helper.rb │ │ └── form_builder.rb │ ├── active_record.rb │ ├── action_view.rb │ ├── formtastic.rb │ ├── mongoid │ │ ├── middleware.rb │ │ └── uniqueness.rb │ ├── simple_form.rb │ ├── active_record │ │ ├── uniqueness.rb │ │ └── middleware.rb │ ├── middleware.rb │ └── active_model.rb ├── generators │ ├── templates │ │ ├── README │ │ └── client_side_validations.rb │ └── client_side_validations │ │ └── install_generator.rb └── client_side_validations.rb ├── test ├── formtastic │ └── cases │ │ ├── helper.rb │ │ ├── test_form_builder.rb │ │ └── test_form_helper.rb ├── simple_form │ └── cases │ │ ├── helper.rb │ │ ├── test_form_builder.rb │ │ └── test_form_helper.rb ├── action_view │ ├── models.rb │ ├── models │ │ ├── post.rb │ │ └── comment.rb │ └── cases │ │ ├── helper.rb │ │ ├── test_legacy_helpers.rb │ │ └── test_helpers.rb ├── javascript │ ├── config.ru │ ├── public │ │ ├── test │ │ │ ├── validators │ │ │ │ ├── presence.js │ │ │ │ ├── confirmation.js │ │ │ │ ├── format.js │ │ │ │ ├── acceptance.js │ │ │ │ ├── exclusion.js │ │ │ │ ├── inclusion.js │ │ │ │ ├── length.js │ │ │ │ ├── uniqueness.js │ │ │ │ └── numericality.js │ │ │ ├── settings.js │ │ │ ├── callbacks │ │ │ │ ├── formAfter.js │ │ │ │ ├── formBefore.js │ │ │ │ ├── formPass.js │ │ │ │ ├── formFail.js │ │ │ │ ├── elementAfter.js │ │ │ │ ├── elementBefore.js │ │ │ │ ├── elementPass.js │ │ │ │ └── elementFail.js │ │ │ ├── form_builders │ │ │ │ ├── validateFormtastic.js │ │ │ │ ├── validateSimpleForm.js │ │ │ │ └── validateForm.js │ │ │ └── validateElement.js │ │ └── vendor │ │ │ ├── jquery.metadata.js │ │ │ └── qunit.css │ ├── views │ │ ├── index.erb │ │ └── layout.erb │ └── server.rb ├── base_helper.rb ├── active_model │ ├── cases │ │ ├── helper.rb │ │ ├── test_base.rb │ │ ├── test_presence_validator.rb │ │ ├── test_confirmation_validator.rb │ │ ├── test_acceptance_validator.rb │ │ ├── test_format_validator.rb │ │ ├── test_exclusion_validator.rb │ │ ├── test_inclusion_validator.rb │ │ ├── test_numericality_validator.rb │ │ ├── test_length_validator.rb │ │ └── test_validations.rb │ └── models │ │ └── person.rb ├── mongoid │ ├── models │ │ └── book.rb │ └── cases │ │ ├── helper.rb │ │ ├── test_base.rb │ │ ├── test_uniqueness_validator.rb │ │ └── test_middleware.rb ├── active_record │ ├── models │ │ ├── guid.rb │ │ └── user.rb │ └── cases │ │ ├── test_base.rb │ │ ├── helper.rb │ │ ├── test_uniqueness_validator.rb │ │ └── test_middleware.rb ├── middleware │ └── cases │ │ ├── test_middleware.rb │ │ └── helper.rb ├── generators │ └── cases │ │ └── test_install_generator.rb └── core_ext │ └── cases │ └── test_core_ext.rb ├── Gemfile ├── client_side_validations.gemspec ├── Rakefile ├── HISTORY ├── README.markdown └── javascript └── rails.validations.js /.rvmrc: -------------------------------------------------------------------------------- 1 | rvm --create use default@client_side_validations > /dev/null 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | tags 6 | test/generators/tmp/* 7 | -------------------------------------------------------------------------------- /lib/client_side_validations/version.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations 2 | VERSION = "3.0.4" 3 | end 4 | -------------------------------------------------------------------------------- /test/formtastic/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'formtastic' 2 | require 'client_side_validations/formtastic' 3 | -------------------------------------------------------------------------------- /test/simple_form/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'simple_form' 2 | require 'client_side_validations/simple_form' 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in client_side_validations.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /test/action_view/models.rb: -------------------------------------------------------------------------------- 1 | require 'active_model' 2 | require 'action_view/models/comment' 3 | require 'action_view/models/post' 4 | -------------------------------------------------------------------------------- /test/javascript/config.ru: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift File.expand_path('..', __FILE__) 2 | require 'server' 3 | run Sinatra::Application 4 | -------------------------------------------------------------------------------- /test/base_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'ruby-debug' 3 | require 'test/unit' 4 | require 'mocha' 5 | 6 | module ClientSideValidations; end 7 | -------------------------------------------------------------------------------- /test/active_model/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'base_helper' 2 | require 'active_model' 3 | require 'client_side_validations/active_model' 4 | require 'active_model/models/person' 5 | -------------------------------------------------------------------------------- /lib/client_side_validations/core_ext.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/json' 2 | require 'client_side_validations/core_ext/range' 3 | require 'client_side_validations/core_ext/regexp' 4 | -------------------------------------------------------------------------------- /test/mongoid/models/book.rb: -------------------------------------------------------------------------------- 1 | class Book 2 | include Mongoid::Document 3 | 4 | field :age, :type => Integer 5 | field :author_name, :type => String 6 | field :author_email, :type => String 7 | end 8 | 9 | -------------------------------------------------------------------------------- /test/active_record/models/guid.rb: -------------------------------------------------------------------------------- 1 | guids_table = %{CREATE TABLE guids (id INTEGER PRIMARY KEY, key text);} 2 | ActiveRecord::Base.connection.execute(guids_table) 3 | 4 | class Guid < ActiveRecord::Base 5 | 6 | end 7 | 8 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_model/format.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActiveModel 2 | module Format 3 | private 4 | 5 | def message_type 6 | :invalid 7 | end 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_model/presence.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActiveModel 2 | module Presence 3 | private 4 | 5 | def message_type 6 | :blank 7 | end 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/client_side_validations/core_ext/range.rb: -------------------------------------------------------------------------------- 1 | class Range 2 | def as_json(options = nil) 3 | [first, last] 4 | end 5 | 6 | def to_json(options = nil) 7 | as_json(options).inspect 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_model/acceptance.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActiveModel 2 | module Acceptance 3 | private 4 | 5 | def message_type 6 | :accepted 7 | end 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/generators/templates/README: -------------------------------------------------------------------------------- 1 | ************************************** 2 | Client Side Validations 3 | 4 | Currently Client Side Validations only 5 | works with jQuery. You'll need to require 6 | jQuery in your layout file before you 7 | require 'rails.validations.js' 8 | -------------------------------------------------------------------------------- /test/active_model/cases/test_base.rb: -------------------------------------------------------------------------------- 1 | require 'active_model/cases/helper' 2 | 3 | class ClientSideValidations::ActiveModelTestBase < ActiveModel::TestCase 4 | include ActiveModel::Validations 5 | 6 | def setup 7 | @person = Person.new 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /test/active_record/cases/test_base.rb: -------------------------------------------------------------------------------- 1 | require 'active_record/cases/helper' 2 | 3 | class ClientSideValidations::ActiveRecordTestBase < ActiveRecord::TestCase 4 | include ActiveRecord::Validations 5 | 6 | def setup 7 | @user = User.new 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /test/middleware/cases/test_middleware.rb: -------------------------------------------------------------------------------- 1 | require 'middleware/cases/helper' 2 | 3 | class ClientSideValidationsMiddleWareTest < Test::Unit::TestCase 4 | def test_if_middleware_is_auto_included 5 | assert Rails.configuration.middleware.include?(ClientSideValidations::Middleware::Validators) 6 | end 7 | end 8 | 9 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_model/exclusion.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActiveModel 2 | module Exclusion 3 | 4 | def client_side_hash(model, attribute) 5 | hash = super 6 | if hash[:in].is_a?(Range) 7 | hash[:range] = hash[:in] 8 | hash.delete(:in) 9 | end 10 | hash 11 | end 12 | 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_model/inclusion.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActiveModel 2 | module Inclusion 3 | 4 | def client_side_hash(model, attribute) 5 | hash = super 6 | if hash[:in].is_a?(Range) 7 | hash[:range] = hash[:in] 8 | hash.delete(:in) 9 | end 10 | hash 11 | end 12 | 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /test/active_record/models/user.rb: -------------------------------------------------------------------------------- 1 | users_table = %{CREATE TABLE users (id INTEGER PRIMARY KEY, age INTEGER, name TEXT, email TEXT, title VARCHAR(5));} 2 | ActiveRecord::Base.connection.execute(users_table) 3 | 4 | class User < ActiveRecord::Base 5 | 6 | end 7 | 8 | class IneptWizard < User; end 9 | class Conjurer < IneptWizard; end 10 | class Thaumaturgist < Conjurer; end 11 | -------------------------------------------------------------------------------- /lib/client_side_validations/core_ext/regexp.rb: -------------------------------------------------------------------------------- 1 | class Regexp 2 | def as_json(options = nil) 3 | Regexp.new inspect.sub("\\A","^").sub("\\Z","$").sub("\\z","$").sub(/^\//,"").sub(/\/[a-z]*$/,""), self.options 4 | end 5 | 6 | def to_json(options = nil) 7 | as_json(options).inspect 8 | end 9 | 10 | def encode_json(encoder) 11 | inspect 12 | end 13 | end 14 | 15 | -------------------------------------------------------------------------------- /lib/client_side_validations/mongoid.rb: -------------------------------------------------------------------------------- 1 | require 'client_side_validations/active_model' 2 | require 'client_side_validations/mongoid/middleware' 3 | 4 | %w{uniqueness}.each do |validator| 5 | require "client_side_validations/mongoid/#{validator}" 6 | validator.capitalize! 7 | eval "Mongoid::Validations::#{validator}Validator.send(:include, ClientSideValidations::Mongoid::#{validator})" 8 | end 9 | 10 | -------------------------------------------------------------------------------- /lib/client_side_validations.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations 2 | end 3 | 4 | require 'client_side_validations/active_model' if defined?(::ActiveModel) 5 | require 'client_side_validations/active_record' if defined?(::ActiveRecord) 6 | require 'client_side_validations/mongoid' if defined?(::Mongoid) 7 | require 'client_side_validations/action_view' 8 | require 'client_side_validations/middleware' if defined?(::Rails) 9 | 10 | -------------------------------------------------------------------------------- /test/active_record/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'base_helper' 2 | require 'active_record' 3 | require 'client_side_validations/active_record' 4 | 5 | # Connection must be establised before anything else 6 | ActiveRecord::Base.establish_connection( 7 | :adapter => defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3', 8 | :database => ':memory:' 9 | ) 10 | 11 | require 'active_record/models/user' 12 | require 'active_record/models/guid' 13 | -------------------------------------------------------------------------------- /test/active_model/models/person.rb: -------------------------------------------------------------------------------- 1 | class PersonValidator < ActiveModel::Validator 2 | def validate(record) 3 | end 4 | end 5 | 6 | class Person 7 | include ActiveModel::Validations 8 | 9 | attr_accessor :first_name, :last_name, :email, :age 10 | 11 | validates_presence_of :first_name 12 | validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i 13 | 14 | def new_record? 15 | true 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/middleware/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'base_helper' 2 | require 'rails' 3 | 4 | # Pulled from railties/test/abstract_unit in Rails 3.1 5 | module TestApp 6 | class Application < Rails::Application 7 | config.root = File.dirname(__FILE__) 8 | config.active_support.deprecation = :log 9 | config.logger = Logger.new(STDOUT) 10 | end 11 | end 12 | 13 | require 'client_side_validations/middleware' 14 | 15 | TestApp::Application.initialize! 16 | -------------------------------------------------------------------------------- /test/mongoid/cases/helper.rb: -------------------------------------------------------------------------------- 1 | require 'base_helper' 2 | require 'mongoid' 3 | require 'client_side_validations/mongoid' 4 | 5 | Mongoid.configure do |config| 6 | name = "client_side_validations_development" 7 | host = "localhost" 8 | config.master = Mongo::Connection.new.db(name) 9 | config.slaves = [ 10 | Mongo::Connection.new(host).db(name) 11 | ] 12 | config.persist_in_safe_mode = false 13 | end 14 | 15 | require 'mongoid/models/book' 16 | 17 | -------------------------------------------------------------------------------- /test/formtastic/cases/test_form_builder.rb: -------------------------------------------------------------------------------- 1 | require 'formtastic/cases/helper' 2 | 3 | class ClientSideValidations::Formtastic::SemanticFormBuilderTest < Test::Unit::TestCase 4 | def test_client_side_form_js_hash 5 | expected = { 6 | :type => 'Formtastic::SemanticFormBuilder', 7 | :inline_error_class => 'inline-errors' 8 | } 9 | assert_equal expected, Formtastic::SemanticFormBuilder.client_side_form_settings(nil, nil) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/mongoid/cases/test_base.rb: -------------------------------------------------------------------------------- 1 | require 'mongoid/cases/helper' 2 | 3 | class ClientSideValidations::MongoidTestBase < Test::Unit::TestCase 4 | include Mongoid::Validations 5 | 6 | def setup 7 | @book = Book.new 8 | end 9 | 10 | def test_uniqueness_client_side_hash 11 | expected_hash = { :message => "is already taken" } 12 | assert_equal expected_hash, UniquenessValidator.new(:attributes => [:name]).client_side_hash(@book, :age) 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/client_side_validations/action_view/form_tag_helper.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActionView::Helpers 2 | module FormTagHelper 3 | private 4 | def html_options_for_form(url_for_options, options, *parameters_for_url) 5 | options.stringify_keys! 6 | html_options = {} 7 | html_options['data-validate'] = options.delete('validate') if options['validate'] 8 | html_options.merge!(super(url_for_options, options, *parameters_for_url)) 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /lib/client_side_validations/active_record.rb: -------------------------------------------------------------------------------- 1 | require 'client_side_validations/active_model' 2 | require 'client_side_validations/active_record/middleware' 3 | 4 | %w{uniqueness}.each do |validator| 5 | require "client_side_validations/active_record/#{validator}" 6 | validator.capitalize! 7 | eval "ActiveRecord::Validations::#{validator}Validator.send(:include, ClientSideValidations::ActiveRecord::#{validator})" 8 | end 9 | 10 | ActiveRecord::Base.send(:include, ClientSideValidations::ActiveModel::Validations) 11 | 12 | -------------------------------------------------------------------------------- /test/simple_form/cases/test_form_builder.rb: -------------------------------------------------------------------------------- 1 | require 'simple_form/cases/helper' 2 | 3 | class ClientSideValidations::SimpleForm::FormBuilderTest < Test::Unit::TestCase 4 | def test_client_side_form_js_hash 5 | expected = { 6 | :type => 'SimpleForm::FormBuilder', 7 | :error_class => :error, 8 | :error_tag => :span, 9 | :wrapper_error_class => :field_with_errors, 10 | :wrapper_tag => :div 11 | } 12 | assert_equal expected, SimpleForm::FormBuilder.client_side_form_settings(nil, nil) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/generators/cases/test_install_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators/test_case' 2 | require 'generators/client_side_validations/install_generator' 3 | 4 | class InstallGeneratorTest < Rails::Generators::TestCase 5 | tests ClientSideValidations::Generators::InstallGenerator 6 | destination File.expand_path('../../tmp', __FILE__) 7 | setup :prepare_destination 8 | 9 | test 'Assert all files are properly created' do 10 | run_generator 11 | assert_file 'config/initializers/client_side_validations.rb' 12 | assert_file 'public/javascripts/rails.validations.js' 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /lib/client_side_validations/action_view.rb: -------------------------------------------------------------------------------- 1 | module ClientSideValidations::ActionView 2 | module Helpers 3 | end 4 | end 5 | 6 | require "client_side_validations/action_view/form_helper" 7 | require "client_side_validations/action_view/form_tag_helper" 8 | require "client_side_validations/action_view/form_builder" 9 | 10 | ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormHelper) 11 | ActionView::Base.send(:include, ClientSideValidations::ActionView::Helpers::FormTagHelper) 12 | ActionView::Helpers::FormBuilder.send(:include, ClientSideValidations::ActionView::Helpers::FormBuilder) 13 | 14 | -------------------------------------------------------------------------------- /test/javascript/public/test/validators/presence.js: -------------------------------------------------------------------------------- 1 | module('Presence options'); 2 | 3 | test('when value is not empty', function() { 4 | var element = $(''); 5 | var options = { message: "failed validation" }; 6 | element.val('not empty'); 7 | equal(clientSideValidations.validators.local.presence(element, options), undefined); 8 | }); 9 | 10 | test('when value is empty', function() { 11 | var element = $(''); 12 | var options = { message: "failed validation" }; 13 | equal(clientSideValidations.validators.local.presence(element, options), "failed validation"); 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /test/javascript/public/test/settings.js: -------------------------------------------------------------------------------- 1 | // hijacks normal form submit; lets it submit to an iframe to prevent 2 | // navigating away from the test suite 3 | $(document).bind('submit', function(e) { 4 | if (!e.isDefaultPrevented()) { 5 | var form = $(e.target), action = form.attr('action'), 6 | name = 'form-frame' + jQuery.guid++, 7 | iframe = $('