client_side_validations-rails_2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/HISTORY +5 -0
- data/README.markdown +45 -0
- data/Rakefile +21 -0
- data/client_side_validations-rails_2.gemspec +35 -0
- data/generators/client_side_validations/client_side_validations_generator.rb +14 -0
- data/lib/client_side_validations/rails_2.rb +5 -0
- data/lib/client_side_validations/rails_2/action_view.rb +7 -0
- data/lib/client_side_validations/rails_2/action_view/form_helper.rb +11 -0
- data/lib/client_side_validations/rails_2/action_view/form_tag_helper.rb +6 -0
- data/lib/client_side_validations/rails_2/active_record.rb +14 -0
- data/lib/client_side_validations/rails_2/active_record/active_model.rb +12 -0
- data/lib/client_side_validations/rails_2/active_record/active_model/validations.rb +51 -0
- data/lib/client_side_validations/rails_2/active_record/active_model/validations/base.rb +25 -0
- data/lib/client_side_validations/rails_2/active_record/active_model/validations/numericality.rb +5 -0
- data/lib/client_side_validations/rails_2/active_record/middleware.rb +42 -0
- data/lib/client_side_validations/rails_2/active_record/validations.rb +23 -0
- data/lib/client_side_validations/rails_2/middleware.rb +22 -0
- data/lib/client_side_validations/rails_2/version.rb +5 -0
- data/test/action_view/cases/helper.rb +155 -0
- data/test/action_view/cases/test_helpers.rb +516 -0
- data/test/action_view/cases/test_legacy_helpers.rb +140 -0
- data/test/action_view/models.rb +2 -0
- data/test/action_view/models/comment.rb +26 -0
- data/test/action_view/models/post.rb +31 -0
- data/test/active_record/cases/helper.rb +13 -0
- data/test/active_record/cases/test_base.rb +10 -0
- data/test/active_record/cases/test_middleware.rb +157 -0
- data/test/active_record/cases/test_validation_reflection.rb +144 -0
- data/test/active_record/cases/test_validations.rb +27 -0
- data/test/active_record/models/guid.rb +7 -0
- data/test/active_record/models/user.rb +11 -0
- data/test/base_helper.rb +10 -0
- data/test/middleware/cases/helper.rb +6 -0
- metadata +237 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/HISTORY
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# ClientSideValidations for Rails 2.x #
|
2
|
+
|
3
|
+
This gem provides a thin wrapper for [ClientSideValidations](https://github.com/bcardarella/client_side_validations)
|
4
|
+
|
5
|
+
## Installation ##
|
6
|
+
|
7
|
+
*This gem requires the [jquery-ujs](https://github.com/rails/jquery-ujs) gem. Please install that before continuing.*
|
8
|
+
|
9
|
+
Add the gem to your `config/environment.rb` file:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
config.gem 'client_side_validations-rails_2', :lib => 'client_side_validations/rails_2'
|
13
|
+
```
|
14
|
+
|
15
|
+
Run the `gems:install` `rake` task:
|
16
|
+
|
17
|
+
```
|
18
|
+
rake gems:install
|
19
|
+
```
|
20
|
+
|
21
|
+
Run the generator
|
22
|
+
|
23
|
+
```
|
24
|
+
script/generate client_side_validations
|
25
|
+
```
|
26
|
+
|
27
|
+
This will install two files
|
28
|
+
|
29
|
+
```
|
30
|
+
config/initializers/client_side_validations.rb
|
31
|
+
public/javascripts/rails.validations.js
|
32
|
+
```
|
33
|
+
|
34
|
+
## Usage ##
|
35
|
+
|
36
|
+
Please follow the instructions for [Rails 3.0 on the ClientSideValidations README](https://github.com/bcardarella/client_side_validations)
|
37
|
+
|
38
|
+
## Legal ##
|
39
|
+
|
40
|
+
Brian Cardarella © 2011
|
41
|
+
|
42
|
+
[@bcardarella](http://twitter.com/bcardarella)
|
43
|
+
|
44
|
+
[Licensed under the MIT license](http://www.opensource.org/licenses/mit-license.php)
|
45
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
multitask :default => 'test:ruby'
|
5
|
+
|
6
|
+
require 'rake/testtask'
|
7
|
+
namespace :test do
|
8
|
+
desc %(Run all tests)
|
9
|
+
multitask :all => ['test:all_rubies']
|
10
|
+
|
11
|
+
desc %(Test Ruby code)
|
12
|
+
Rake::TestTask.new(:ruby) do |test|
|
13
|
+
test.libs << 'lib' << 'test'
|
14
|
+
test.pattern = 'test/*/cases/**/test_*.rb'
|
15
|
+
test.verbose = true
|
16
|
+
end
|
17
|
+
|
18
|
+
task :all_rubies do
|
19
|
+
system "rvm ruby-1.8.7@client_side_validations-rails_2,ruby-1.9.2@client_side_validations-rails_2 rake test:ruby"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "client_side_validations/rails_2/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "client_side_validations-rails_2"
|
7
|
+
s.version = ClientSideValidations::Rails2::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Brian Cardarella"]
|
10
|
+
s.email = ["bcardarella@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Client Side Validations support for Rails 2.x}
|
13
|
+
s.description = %q{Client Side Validations support for Rails 2.x}
|
14
|
+
|
15
|
+
s.files = `git ls-files -- {lib/*,generators/*,*.gemspec}`.split("\n")
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'activesupport', '~> 2.3.0'
|
22
|
+
s.add_dependency 'client_side_validations', '3.1.0.beta.2'
|
23
|
+
|
24
|
+
s.add_development_dependency 'activerecord', '~> 2.3.0'
|
25
|
+
s.add_development_dependency 'actionpack', '~> 2.3.0'
|
26
|
+
s.add_development_dependency 'sqlite3'
|
27
|
+
s.add_development_dependency 'mocha'
|
28
|
+
s.add_development_dependency 'rack-test'
|
29
|
+
|
30
|
+
if RUBY_VERSION >= "1.9"
|
31
|
+
s.add_development_dependency 'ruby-debug19'
|
32
|
+
else
|
33
|
+
s.add_development_dependency 'ruby-debug'
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'client_side_validations/files'
|
2
|
+
|
3
|
+
class ClientSideValidationsGenerator < Rails::Generator::Base
|
4
|
+
def manifest
|
5
|
+
record do |c|
|
6
|
+
c.file(ClientSideValidations::Files::Initializer, 'config/initializers/client_side_validations.rb')
|
7
|
+
c.file(ClientSideValidations::Files::Javascript, 'public/javascripts/rails.validations.js')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def source_path(relative_path)
|
12
|
+
relative_path
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module ClientSideValidations::Rails2::ActionView; end
|
2
|
+
|
3
|
+
require 'client_side_validations/action_view'
|
4
|
+
require 'client_side_validations/rails_2/action_view/form_helper'
|
5
|
+
|
6
|
+
ActionView::Base.send(:include, ClientSideValidations::Rails2::ActionView::Helpers::FormHelper)
|
7
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ClientSideValidations::Rails2
|
2
|
+
module ActiveRecord; end
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'client_side_validations/rails_2/active_record/active_model'
|
6
|
+
require 'client_side_validations/rails_2/active_record/validations'
|
7
|
+
require 'client_side_validations/rails_2/active_record/middleware'
|
8
|
+
|
9
|
+
require 'client_side_validations/active_model'
|
10
|
+
|
11
|
+
ActiveModel::Validations::BaseValidator.send(:include, ActiveModel::Validator)
|
12
|
+
ActiveRecord::Base.send(:include, ActiveModel::Validations)
|
13
|
+
ActiveRecord::Base.send(:extend, ActiveModel::Validations::ClassMethods)
|
14
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This is to backport the ActiveModel namespacing to ActiveRecord 2.x
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module Validator; end
|
5
|
+
module Validations; end
|
6
|
+
class Errors
|
7
|
+
CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'client_side_validations/rails_2/active_record/active_model/validations'
|
12
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveModel::Validations
|
2
|
+
module ClassMethods
|
3
|
+
def _validators
|
4
|
+
@_validators ||= Hash.new { |hash, key| hash[key] = [] }
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def _validators
|
9
|
+
self.class._validators
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'client_side_validations/rails_2/active_record/active_model/validations/base'
|
14
|
+
|
15
|
+
%w{
|
16
|
+
acceptance
|
17
|
+
confirmation
|
18
|
+
exclusion
|
19
|
+
format
|
20
|
+
inclusion
|
21
|
+
length
|
22
|
+
numericality
|
23
|
+
presence
|
24
|
+
}.each do |validator|
|
25
|
+
eval <<-MODULE
|
26
|
+
|
27
|
+
module ActiveModel::Validations
|
28
|
+
const_set '#{validator.capitalize}Validator', Class.new(BaseValidator)
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
define_method "validates_#{validator}_of" do |*attr_names|
|
32
|
+
options = attr_names.extract_options!
|
33
|
+
attr_names.each do |name|
|
34
|
+
self._validators[name] << #{validator.capitalize}Validator.new(name, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
super(*((attr_names << options).compact))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
MODULE
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'client_side_validations/rails_2/active_record/active_model/validations/numericality'
|
45
|
+
|
46
|
+
module ActiveModel::Validations::ClassMethods
|
47
|
+
def validates_size_of(*attr_names)
|
48
|
+
validates_length_of(*attr_names)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveModel::Validations
|
2
|
+
class BaseValidator
|
3
|
+
attr_accessor :attributes, :options
|
4
|
+
|
5
|
+
def initialize(attributes, options = {})
|
6
|
+
self.attributes = attributes
|
7
|
+
self.options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
class_equality = self.class == other.class
|
12
|
+
attribute_equality = self.attributes == other.attributes
|
13
|
+
options_equality = self.options == other.options
|
14
|
+
class_equality && attribute_equality && options_equality
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.kind
|
18
|
+
@kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def kind
|
22
|
+
self.class.kind
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ClientSideValidations::ActiveRecord
|
2
|
+
class Middleware
|
3
|
+
|
4
|
+
def self.is_unique?(finder_class, attr_name, value, params)
|
5
|
+
column = finder_class.columns_hash[attr_name.to_s]
|
6
|
+
connection = finder_class.connection
|
7
|
+
|
8
|
+
if value.nil?
|
9
|
+
comparison_operator = "IS ?"
|
10
|
+
elsif column.text?
|
11
|
+
comparison_operator = "#{connection.case_sensitive_equality_operator} ?"
|
12
|
+
value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s
|
13
|
+
else
|
14
|
+
comparison_operator = "= ?"
|
15
|
+
end
|
16
|
+
|
17
|
+
sql_attribute = "#{finder_class.quoted_table_name}.#{connection.quote_column_name(attr_name)}"
|
18
|
+
|
19
|
+
if value.nil? || (params[:case_sensitive] == 'true' || !column.text?)
|
20
|
+
condition_sql = "#{sql_attribute} #{comparison_operator}"
|
21
|
+
condition_params = [value]
|
22
|
+
else
|
23
|
+
condition_sql = "LOWER(#{sql_attribute}) #{comparison_operator}"
|
24
|
+
condition_params = [value.mb_chars.downcase]
|
25
|
+
end
|
26
|
+
|
27
|
+
(params[:scope] || {}).each do |scope_item, scope_value|
|
28
|
+
condition_sql << " AND " << finder_class.send(:attribute_condition, "#{finder_class.quoted_table_name}.#{connection.quote_column_name(scope_item)}", scope_value)
|
29
|
+
condition_params << scope_value
|
30
|
+
end
|
31
|
+
|
32
|
+
if params[:id]
|
33
|
+
condition_sql << " AND #{finder_class.quoted_table_name}.#{finder_class.primary_key} <> ?"
|
34
|
+
condition_params << params[:id]
|
35
|
+
end
|
36
|
+
|
37
|
+
finder_class.send(:with_exclusive_scope) do
|
38
|
+
!finder_class.exists?([condition_sql, *condition_params])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'client_side_validations/active_record/uniqueness'
|
2
|
+
|
3
|
+
module ActiveRecord::Validations
|
4
|
+
class UniquenessValidator < ActiveModel::Validations::BaseValidator
|
5
|
+
include ClientSideValidations::ActiveRecord::Uniqueness
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClientSideValidations::Rails2::ActiveRecord::Validations
|
10
|
+
module ClassMethods
|
11
|
+
def validates_uniqueness_of(*attr_names)
|
12
|
+
options = attr_names.extract_options!
|
13
|
+
attr_names.each do |name|
|
14
|
+
self._validators[name] << ::ActiveRecord::Validations::UniquenessValidator.new(name, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
super(*((attr_names << options).compact))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveRecord::Base.send(:extend, ClientSideValidations::Rails2::ActiveRecord::Validations::ClassMethods)
|
23
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'client_side_validations/middleware'
|
4
|
+
|
5
|
+
module ClientSideValidations
|
6
|
+
|
7
|
+
module Middleware
|
8
|
+
class Base
|
9
|
+
def initialize(env)
|
10
|
+
self.body = ''
|
11
|
+
self.status = 200
|
12
|
+
self.request = ActionController::Request.new(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if defined?(Rails)
|
19
|
+
Rails.configuration.after_initialize do
|
20
|
+
Rails.configuration.middleware.use ClientSideValidations::Middleware::Validators
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'base_helper'
|
2
|
+
require 'action_view'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'action_view/test_case'
|
5
|
+
require 'client_side_validations/rails_2/action_view'
|
6
|
+
require 'action_view/models'
|
7
|
+
|
8
|
+
module ActionViewTestSetup
|
9
|
+
include ::ClientSideValidations::ActionView::Helpers::FormHelper
|
10
|
+
include ::ClientSideValidations::ActionView::Helpers::FormTagHelper
|
11
|
+
include ::ClientSideValidations::Rails2::ActionView::Helpers::FormHelper
|
12
|
+
|
13
|
+
def setup
|
14
|
+
super
|
15
|
+
|
16
|
+
# Create "label" locale for testing I18n label helpers
|
17
|
+
I18n.backend.store_translations 'label', {
|
18
|
+
:activemodel => {
|
19
|
+
:attributes => {
|
20
|
+
:post => {
|
21
|
+
:cost => "Total cost"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
},
|
25
|
+
:helpers => {
|
26
|
+
:label => {
|
27
|
+
:post => {
|
28
|
+
:body => "Write entire text here"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
# Create "submit" locale for testing I18n submit helpers
|
35
|
+
I18n.backend.store_translations 'submit', {
|
36
|
+
:helpers => {
|
37
|
+
:submit => {
|
38
|
+
:create => 'Create %{model}',
|
39
|
+
:update => 'Confirm %{model} changes',
|
40
|
+
:submit => 'Save changes',
|
41
|
+
:another_post => {
|
42
|
+
:update => 'Update your %{model}'
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
@post = Post.new
|
49
|
+
@comment = Comment.new
|
50
|
+
def @post.errors()
|
51
|
+
Class.new{
|
52
|
+
def [](field); field == "author_name" ? ["can't be empty"] : [] end
|
53
|
+
def empty?() false end
|
54
|
+
def count() 1 end
|
55
|
+
def full_messages() [ "Author name can't be empty" ] end
|
56
|
+
}.new
|
57
|
+
end
|
58
|
+
def @post.id; 123; end
|
59
|
+
def @post.id_before_type_cast; 123; end
|
60
|
+
def @post.to_param; '123'; end
|
61
|
+
|
62
|
+
@post.persisted = true
|
63
|
+
@post.title = "Hello World"
|
64
|
+
@post.author_name = ""
|
65
|
+
@post.body = "Back to the hill and over it again!"
|
66
|
+
@post.secret = 1
|
67
|
+
@post.written_on = Date.new(2004, 6, 15)
|
68
|
+
end
|
69
|
+
|
70
|
+
def url_for(object)
|
71
|
+
@url_for_options = object
|
72
|
+
if object.is_a?(Hash)
|
73
|
+
"http://www.example.com"
|
74
|
+
else
|
75
|
+
super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def snowman(method = nil)
|
80
|
+
txt = %{<div style="margin:0;padding:0;display:inline">}
|
81
|
+
txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
|
82
|
+
txt << %{</div>}
|
83
|
+
end
|
84
|
+
|
85
|
+
def form_text(action = "http://www.example.com", id = nil, html_class = nil, remote = nil, validators = nil)
|
86
|
+
txt = %{<form action="#{action}"}
|
87
|
+
txt << %{ data-remote="true"} if remote
|
88
|
+
txt << %{ class="#{html_class}"} if html_class
|
89
|
+
txt << %{ data-validate="true"} if validators
|
90
|
+
txt << %{ id="#{id}"} if id
|
91
|
+
txt << %{ method="post"}
|
92
|
+
txt << %{ novalidate="novalidate"} if validators
|
93
|
+
txt << %{>}
|
94
|
+
end
|
95
|
+
|
96
|
+
def whole_form(action = "http://www.example.com", id = nil, html_class = nil, options = nil)
|
97
|
+
contents = block_given? ? yield : ""
|
98
|
+
|
99
|
+
if options.is_a?(Hash)
|
100
|
+
method, remote, validators = options.values_at(:method, :remote, :validators)
|
101
|
+
else
|
102
|
+
method = options
|
103
|
+
end
|
104
|
+
|
105
|
+
html = form_text(action, id, html_class, remote, validators) + snowman(method) + (contents || "") + "</form>"
|
106
|
+
|
107
|
+
if options.is_a?(Hash) && options[:validators]
|
108
|
+
build_script_tag(html, id, options[:validators])
|
109
|
+
else
|
110
|
+
html
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_script_tag(html, id, validators)
|
115
|
+
(html || "") + %Q{<script>window['#{id}'] = #{client_side_form_settings_helper.merge(:validators => validators).to_json};</script>}
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
def comments_path(post)
|
120
|
+
"/posts/#{post.id}/comments"
|
121
|
+
end
|
122
|
+
alias_method :post_comments_path, :comments_path
|
123
|
+
|
124
|
+
def comment_path(post, comment)
|
125
|
+
"/posts/#{post.id}/comments/#{comment.id}"
|
126
|
+
end
|
127
|
+
alias_method :post_comment_path, :comment_path
|
128
|
+
|
129
|
+
def admin_comments_path(post)
|
130
|
+
"/admin/posts/#{post.id}/comments"
|
131
|
+
end
|
132
|
+
alias_method :admin_post_comments_path, :admin_comments_path
|
133
|
+
|
134
|
+
def admin_comment_path(post, comment)
|
135
|
+
"/admin/posts/#{post.id}/comments/#{comment.id}"
|
136
|
+
end
|
137
|
+
alias_method :admin_post_comment_path, :admin_comment_path
|
138
|
+
|
139
|
+
def posts_path
|
140
|
+
"/posts"
|
141
|
+
end
|
142
|
+
|
143
|
+
def post_path(post, options = {})
|
144
|
+
if options[:format]
|
145
|
+
"/posts/#{post.id}.#{options[:format]}"
|
146
|
+
else
|
147
|
+
"/posts/#{post.id}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def protect_against_forgery?
|
152
|
+
false
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|