wanew_client_validate 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ # Include hook code here
2
+
3
+ require 'client_validate'
@@ -0,0 +1,16 @@
1
+ module WaNew
2
+ module ClientValidate
3
+ module ActionView
4
+ module Helpers
5
+
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+
12
+ require 'wanew/client_validate/action_view/form_helper'
13
+ require 'wanew/client_validate/action_view/form_builder'
14
+
15
+ ActionView::Base.send(:include, WaNew::ClientValidate::ActionView::Helpers::FormHelper)
16
+ ActionView::Helpers::FormBuilder.send(:include, WaNew::ClientValidate::ActionView::Helpers::FormBuilder)
@@ -0,0 +1,103 @@
1
+ module WaNew::ClientValidate::ActionView::Helpers
2
+ module FormBuilder
3
+
4
+ def self.included(base)
5
+ (base.field_helpers - %w(apply_form_for_options! label check_box radio_button fields_for hidden_field)).each do |selector|
6
+ base.class_eval <<-RUBY_EVAL
7
+ def #{selector}_with_client_validations(method, options = {})
8
+ apply_client_validators(method, options)
9
+ options.delete(:validate)
10
+ #{selector}_without_client_validations(method, options)
11
+ end
12
+ RUBY_EVAL
13
+
14
+ base.class_eval { alias_method_chain selector, :client_validations }
15
+ end
16
+
17
+ base.class_eval do
18
+ alias_method_chain :initialize, :client_validations
19
+ alias_method_chain :fields_for, :client_validations
20
+ alias_method_chain :check_box, :client_validations
21
+ alias_method_chain :radio_button, :client_validations
22
+ alias_method_chain :select, :client_validations
23
+ alias_method_chain :collection_select, :client_validations
24
+ alias_method_chain :grouped_collection_select, :client_validations
25
+ alias_method_chain :time_zone_select, :client_validations
26
+
27
+ def self.client_form_settings(options, form_helper)
28
+ {
29
+ #:type => self.to_s,
30
+ #:input_tag => form_helper.class.field_error_proc.call(%{<span id="input_tag" />}, Struct.new(:error_message, :tag_id).new([], "")),
31
+ #:label_tag => form_helper.class.field_error_proc.call(%{<label id="label_tag" />}, Struct.new(:error_message, :tag_id).new([], ""))
32
+ }
33
+ end
34
+ end
35
+ end
36
+
37
+ def initialize_with_client_validations(object_name, object, template, options, proc)
38
+ initialize_without_client_validations(object_name, object, template, options, proc)
39
+ @options[:validators] = {}
40
+ end
41
+
42
+ def fields_for_with_client_validations(record_or_name_or_array, *args, &block)
43
+ options = args.extract_options!
44
+ options[:validate] ||= @options[:validate] if @options[:validate] && !options.key?(:validate)
45
+ fields_for_without_client_validations(record_or_name_or_array, *(args << options), &block)
46
+ end
47
+
48
+ def check_box_with_client_validations(method, options = {}, checked_value = "1", unchecked_value = "0")
49
+ apply_client_validators(method, options)
50
+ check_box_without_client_validations(method, options, checked_value, unchecked_value)
51
+ end
52
+
53
+ def radio_button_with_client_validations(method, tag_value, options = {})
54
+ apply_client_validators(method, options)
55
+ radio_button_without_client_validations(method, tag_value, options)
56
+ end
57
+
58
+ def select_with_client_validations(method, choices, options = {}, html_options = {})
59
+ apply_client_validators(method, html_options)
60
+ select_without_client_validations(method, choices, options, html_options)
61
+ end
62
+
63
+ def collection_select_with_client_validations(method, collection, value_method, text_method, options = {}, html_options = {})
64
+ apply_client_validators(method, html_options)
65
+ collection_select_without_client_validations(method, collection, value_method, text_method, options, html_options)
66
+ end
67
+
68
+ def grouped_collection_select_with_client_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
69
+ apply_client_validators(method, html_options)
70
+ grouped_collection_select_without_client_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
71
+ end
72
+
73
+ def time_zone_select_with_client_validations(method, priority_zones = nil, options = {}, html_options = {})
74
+ apply_client_validators(method, html_options)
75
+ time_zone_select_without_client_validations(method, priority_zones = nil, options, html_options)
76
+ end
77
+
78
+ private
79
+
80
+ def apply_client_validators(method, options = {})
81
+ if @options[:validate] && options[:validate] != false && validators = filter_validators(@object.client_validation_hash[method], options[:validate])
82
+
83
+ options.merge!("validate" => validators.to_json)
84
+
85
+ @options[:validators].merge!("#{@object_name}[#{method}]" => validators)
86
+ end
87
+ end
88
+
89
+ def filter_validators(validators, filters)
90
+ if validators
91
+ filtered_validators = validators.inject({}) do |filtered_validators, validator|
92
+ unless filters && filters.key?(validator.first) && !filters[validator.first]
93
+ filtered_validators[validator.first] = validator.last
94
+ end
95
+
96
+ filtered_validators
97
+ end
98
+
99
+ filtered_validators.empty? ? nil : filtered_validators
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,76 @@
1
+ module WaNew::ClientValidate::ActionView::Helpers
2
+ module FormHelper
3
+ def form_for(record_or_name_or_array, *args, &proc)
4
+ raise ArgumentError, "Missing block" unless block_given?
5
+
6
+ options = args.extract_options!
7
+
8
+ case record_or_name_or_array
9
+ when String, Symbol
10
+ ActiveSupport::Deprecation.warn("Using form_for(:name, @resource) is deprecated. Please use form_for(@resource, :as => :name) instead.", caller) unless args.empty?
11
+ object_name = record_or_name_or_array
12
+ when Array
13
+ object = record_or_name_or_array.last
14
+ object_name = options[:as] || ActiveModel::Naming.singular(object)
15
+ apply_form_for_options!(record_or_name_or_array, options)
16
+ args.unshift object
17
+ else
18
+ object = record_or_name_or_array
19
+ object_name = options[:as] || ActiveModel::Naming.singular(object)
20
+ apply_form_for_options!([object], options)
21
+ args.unshift object
22
+ end
23
+
24
+ (options[:html] ||= {})[:remote] = true if options.delete(:remote)
25
+
26
+ @validators = {}
27
+ # Order matters here. Rails mutates the options object
28
+ script = client_form_settings(object, options)
29
+ form = super(record_or_name_or_array, *(args << options), &proc)
30
+ # Because of the load order requirement above this sub is necessary
31
+ # Would be nice to not do this
32
+ "#{form}#{script ? script.sub('"validator_hash"', @validators.to_json) : nil}#{script_bind(dom_id(object))}".html_safe
33
+ end
34
+
35
+
36
+ def apply_form_for_options!(object_or_array, options)
37
+ super
38
+ options[:html][:validate] = true if options[:validate]
39
+ end
40
+
41
+ def fields_for(record_or_name_or_array, *args, &block)
42
+ output = super
43
+ @validators.merge!(args.last[:validators]) if @validators
44
+ output
45
+ end
46
+
47
+ private
48
+
49
+ def client_form_settings(object, options)
50
+ if options[:validate]
51
+ builder = options[:builder] || ActionView::Base.default_form_builder
52
+ if options[:html] && options[:html][:id]
53
+ var_name = options[:html][:id]
54
+ else
55
+ var_name = if object.respond_to?(:persisted?) && object.persisted?
56
+ options[:as] ? "#{options[:as]}_edit" : dom_id(object, :edit)
57
+ else
58
+ options[:as] ? "#{options[:as]}_new" : dom_id(object)
59
+ end
60
+ end
61
+
62
+ content_tag(:script, :type=>'text/javascript') do
63
+ "var #{var_name} = #{builder.client_form_settings(options, self).merge(:validators => 'validator_hash').to_json};".html_safe
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+ def script_bind(id)
70
+ content_tag(:script, :type=>'text/javascript') do
71
+ "$('##{id}').validate();"
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,14 @@
1
+ module WaNew
2
+ module ClientValidate
3
+ module ActiveModel
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'active_model/validator'
9
+
10
+ require 'wanew/client_validate/active_model/validators'
11
+ require 'wanew/client_validate/active_model/validator'
12
+
13
+ ActiveModel::Validations::HelperMethods.send(:include,
14
+ WaNew::ClientValidate::ActionView::Validations::HelperMethods) if defined?(:ActiveModel)
@@ -0,0 +1,44 @@
1
+ module WaNew::ClientValidate::ActiveModel
2
+ module Validator
3
+
4
+ def client_hash(model, attribute)
5
+ extra_options = options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:on, :allow_blank])
6
+ { :message => model.errors.generate_message(attribute, message_type, extra_options) }.merge(extra_options)
7
+ end
8
+
9
+ private
10
+
11
+ def message_type
12
+ kind
13
+ end
14
+ end
15
+
16
+ module Validations
17
+ def client_validation_hash
18
+ _validators.except(nil, :block).inject({}) do |attr_hash, attr|
19
+
20
+ validator_hash = attr[1].inject({}) do |kind_hash, validator|
21
+ client_hash = validator.client_hash(self, attr[0])
22
+ # Yeah yeah, #new_record? is not part of ActiveModel :p
23
+ if (can_use_for_client_validation?(client_hash, validator))
24
+ kind_hash.merge!(validator.kind => client_hash.except(:on))
25
+ else
26
+ kind_hash.merge!({})
27
+ end
28
+ end
29
+
30
+ attr_hash.merge!(attr[0] => validator_hash)
31
+ end.delete_if { |key, value| value.blank? }
32
+ end
33
+
34
+ private
35
+
36
+ def can_use_for_client_validation?(client_hash, validator)
37
+ ((self.respond_to?(:new_record?) && client_hash[:on] == (self.new_record? ? :create : :update)) || client_hash[:on].nil?) && !validator.options.key?(:if) && !validator.options.key?(:unless) && validator.kind != :block
38
+ end
39
+ end
40
+ end
41
+
42
+
43
+ ActiveModel::Validator.send(:include, WaNew::ClientValidate::ActiveModel::Validator)
44
+ ActiveModel::Validations.send(:include, WaNew::ClientValidate::ActiveModel::Validations)
@@ -0,0 +1,20 @@
1
+ module WaNew::ClientValidate::ActionView::Validations
2
+ module HelperMethods
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+
7
+ def validates_presence_of_with_client(*attr_names)
8
+ options = attr_names.extract_options!
9
+ options[:message] ||= ""
10
+ options[:message] += " with client!"
11
+ attr_names << options;
12
+
13
+ validates_presence_of_without_client(*attr_names)
14
+ end
15
+
16
+ alias_method_chain :validates_presence_of, :client
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ require 'wanew/client_validate/active_model'
2
+ require 'wanew/client_validate/active_record/middleware'
3
+
4
+ %w{uniqueness}.each do |validator|
5
+ require "wanew/client_validate/active_record/#{validator}"
6
+ validator.capitalize!
7
+ eval "ActiveRecord::Validations::#{validator}Validator.send(:include, WaNew::ClientValidate::ActiveRecord::#{validator})"
8
+ end
9
+
10
+ ActiveRecord::Base.send(:include, WaNew::ClientValidate::ActiveModel::Validations)
11
+
@@ -0,0 +1,29 @@
1
+ module WaNew::ClientValidate::ActiveRecord
2
+ class Middleware
3
+
4
+ def self.is_unique?(klass, attribute, value, params)
5
+ column = klass.columns_hash[attribute.to_s]
6
+ value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?
7
+
8
+ t = klass.arel_table
9
+
10
+ if params[:case_sensitive] == 'true'
11
+ if t.engine.connection.instance_variable_get("@config")[:adapter] == 'mysql'
12
+ relation = Arel::Nodes::SqlLiteral.new("BINARY #{t[attribute].eq(value).to_sql}")
13
+ else
14
+ relation = t[attribute].eq(value)
15
+ end
16
+ else
17
+ relation = t[attribute].matches(value)
18
+ end
19
+
20
+ relation = relation.and(t.primary_key.not_eq(params[:id])) if params[:id]
21
+
22
+ (params[:scope] || {}).each do |key, value|
23
+ relation = relation.and(t[key].eq(value))
24
+ end
25
+
26
+ !klass.where(relation).exists?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module WaNew::ClientValidate::ActiveRecord
2
+ module Uniqueness
3
+ def client_hash(model, attribute)
4
+ extra_options = options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:on, :allow_blank])
5
+ hash = { :message => model.errors.generate_message(attribute, message_type, extra_options.except(:case_sensitive, :scope)) }
6
+ hash = hash.merge(extra_options).merge(model.new_record? ? {} : { :id => model.id })
7
+
8
+ if hash[:scope].present?
9
+ hash[:scope] = Array.wrap(hash[:scope]).inject({}) do |scope_hash, scope_item|
10
+ scope_hash.merge!(scope_item => model.send(scope_item))
11
+ end
12
+ else
13
+ hash.delete(:scope)
14
+ end
15
+
16
+ hash
17
+ end
18
+
19
+ private
20
+
21
+ def message_type
22
+ :taken
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+
3
+ module WaNew::ClientValidate
4
+
5
+ module Middleware
6
+
7
+ class Validators
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ case env['PATH_INFO']
14
+ when %r{\/validators\/(\w+)\.json}
15
+ "::WaNew::ClientValidate::Middleware::#{$1.camelize}".constantize.new(env).response
16
+ else
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+
22
+ class Base
23
+ attr_accessor :request, :body, :status
24
+
25
+ def initialize(env)
26
+ self.body = ''
27
+ self.status = 200
28
+ self.request = ActionDispatch::Request.new(env)
29
+ end
30
+
31
+ def response
32
+ [status, {'Content-Type' => content_type, 'Content-Length' => body.length.to_s}, [body]]
33
+ end
34
+
35
+ def content_type
36
+ 'application/json'
37
+ end
38
+ end
39
+
40
+ class Uniqueness < Base
41
+ IGNORE_PARAMS = %w{case_sensitive id scope}
42
+
43
+ def response
44
+ if is_unique?
45
+ self.status = 404
46
+ self.body = 'true'
47
+ else
48
+ self.status = 200
49
+ self.body = 'false'
50
+ end
51
+ super
52
+ end
53
+
54
+ private
55
+
56
+ def is_unique?
57
+ resource = extract_resource
58
+ klass = resource.classify.constantize
59
+ attribute = request.params[resource].keys.first
60
+ value = request.params[resource][attribute]
61
+
62
+ if (defined?(::ActiveRecord::Base) && klass < ::ActiveRecord::Base)
63
+ middleware_klass = WaNew::ClientValidate::ActiveRecord::Middleware
64
+ end
65
+
66
+ middleware_klass.is_unique?(klass, attribute, value, request.params)
67
+ end
68
+
69
+ def extract_resource
70
+ parent_key = (request.params.keys - IGNORE_PARAMS).first
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ class Engine < ::Rails::Engine
77
+ config.app_middleware.use WaNew::ClientValidate::Middleware::Validators
78
+ end
79
+
80
+ end
81
+
@@ -0,0 +1,5 @@
1
+ module WaNew
2
+ module ClientValidate
3
+ VERSION = "0.0.11"
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ # ClientValidate
2
+ module WaNew
3
+ module ClientValidate
4
+ end
5
+ end
6
+
7
+
8
+ require 'wanew/client_validate/action_view'
9
+ require 'wanew/client_validate/active_model'
10
+ require 'wanew/client_validate/active_record'
11
+ require 'wanew/client_validate/middleware'
12
+
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wanew_client_validate
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 11
10
+ version: 0.0.11
11
+ platform: ruby
12
+ authors:
13
+ - wanliu corporation
14
+ - hysios
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-05-31 00:00:00 +08:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: Client Validate mainly appiled for WaNew Engine in the browser client side validate utils
24
+ email:
25
+ - hysios@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/wanew/client_validate/action_view/form_builder.rb
34
+ - lib/wanew/client_validate/action_view/form_helper.rb
35
+ - lib/wanew/client_validate/action_view.rb
36
+ - lib/wanew/client_validate/active_model/validator.rb
37
+ - lib/wanew/client_validate/active_model/validators.rb
38
+ - lib/wanew/client_validate/active_model.rb
39
+ - lib/wanew/client_validate/active_record/middleware.rb
40
+ - lib/wanew/client_validate/active_record/uniqueness.rb
41
+ - lib/wanew/client_validate/active_record.rb
42
+ - lib/wanew/client_validate/middleware.rb
43
+ - lib/wanew/client_validate/version.rb
44
+ - lib/wanew_client_validate.rb
45
+ - MIT-LICENSE
46
+ - init.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/hysios/client_validate
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 23
71
+ segments:
72
+ - 1
73
+ - 3
74
+ - 6
75
+ version: 1.3.6
76
+ requirements: []
77
+
78
+ rubyforge_project: wanew_client_validate
79
+ rubygems_version: 1.5.2
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: WaNew Client Side Validations(like ClientSideValidations)
83
+ test_files: []
84
+