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.
Files changed (36) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/HISTORY +5 -0
  4. data/README.markdown +45 -0
  5. data/Rakefile +21 -0
  6. data/client_side_validations-rails_2.gemspec +35 -0
  7. data/generators/client_side_validations/client_side_validations_generator.rb +14 -0
  8. data/lib/client_side_validations/rails_2.rb +5 -0
  9. data/lib/client_side_validations/rails_2/action_view.rb +7 -0
  10. data/lib/client_side_validations/rails_2/action_view/form_helper.rb +11 -0
  11. data/lib/client_side_validations/rails_2/action_view/form_tag_helper.rb +6 -0
  12. data/lib/client_side_validations/rails_2/active_record.rb +14 -0
  13. data/lib/client_side_validations/rails_2/active_record/active_model.rb +12 -0
  14. data/lib/client_side_validations/rails_2/active_record/active_model/validations.rb +51 -0
  15. data/lib/client_side_validations/rails_2/active_record/active_model/validations/base.rb +25 -0
  16. data/lib/client_side_validations/rails_2/active_record/active_model/validations/numericality.rb +5 -0
  17. data/lib/client_side_validations/rails_2/active_record/middleware.rb +42 -0
  18. data/lib/client_side_validations/rails_2/active_record/validations.rb +23 -0
  19. data/lib/client_side_validations/rails_2/middleware.rb +22 -0
  20. data/lib/client_side_validations/rails_2/version.rb +5 -0
  21. data/test/action_view/cases/helper.rb +155 -0
  22. data/test/action_view/cases/test_helpers.rb +516 -0
  23. data/test/action_view/cases/test_legacy_helpers.rb +140 -0
  24. data/test/action_view/models.rb +2 -0
  25. data/test/action_view/models/comment.rb +26 -0
  26. data/test/action_view/models/post.rb +31 -0
  27. data/test/active_record/cases/helper.rb +13 -0
  28. data/test/active_record/cases/test_base.rb +10 -0
  29. data/test/active_record/cases/test_middleware.rb +157 -0
  30. data/test/active_record/cases/test_validation_reflection.rb +144 -0
  31. data/test/active_record/cases/test_validations.rb +27 -0
  32. data/test/active_record/models/guid.rb +7 -0
  33. data/test/active_record/models/user.rb +11 -0
  34. data/test/base_helper.rb +10 -0
  35. data/test/middleware/cases/helper.rb +6 -0
  36. metadata +237 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in client_side_validations-rails_2.gemspec
4
+ gemspec
data/HISTORY ADDED
@@ -0,0 +1,5 @@
1
+ == 0.0.1
2
+ Wrapper for ClientSideValidations
3
+ Added ActiveModel API to ActiveRecord 2.x
4
+ concat script from form_for ClientSideValidations
5
+ Wrote ActiveRecord 2.x middleware for Uniqueness
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,5 @@
1
+ module ClientSideValidations::Rails2; end
2
+
3
+ require 'client_side_validations/rails_2/middleware'
4
+ require 'client_side_validations/rails_2/action_view'
5
+ require 'client_side_validations/rails_2/active_record'
@@ -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,11 @@
1
+ module ClientSideValidations::Rails2::ActionView::Helpers
2
+ module FormHelper
3
+ def form_for(record_or_name_or_array, *args, &proc)
4
+ html = super
5
+ if match = html.match(/<script.+$/)
6
+ concat(match[0])
7
+ end
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,6 @@
1
+ module ClientSideValidations::Rails2::ActionView::Helpers
2
+ module FormTagHelper
3
+
4
+ end
5
+ end
6
+
@@ -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,5 @@
1
+ class ActiveModel::Validations::NumericalityValidator
2
+ CHECKS = { :greater_than => :>, :greater_than_or_equal_to => :>=,
3
+ :equal_to => :==, :less_than => :<, :less_than_or_equal_to => :<=,
4
+ :odd => :odd?, :even => :even? }.freeze
5
+ 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,5 @@
1
+ module ClientSideValidations
2
+ module Rails2
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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