client_side_validations-rails_2 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|