Ticket #861: js_validation.diff
| File js_validation.diff, 8.1 kB (added by sebastian.kanthak@muehlheim.de, 3 years ago) |
|---|
-
activerecord/test/validation_reflection_test.rb
old new 1 require 'abstract_unit' 2 require 'fixtures/topic' 3 require 'set' 4 5 class ValidationReflectionTest < Test::Unit::TestCase 6 fixtures :topics 7 8 def setup 9 Topic.write_inheritable_attribute(:validate, nil) 10 Topic.write_inheritable_attribute(:validate_on_create, nil) 11 Topic.write_inheritable_attribute(:validate_on_update, nil) 12 Topic.write_inheritable_attribute("validations", nil) 13 end 14 15 def test_reflect_on_all_validations 16 Topic.validates_presence_of(:title, :content) 17 Topic.validates_acceptance_of(:terms_of_service) 18 19 assert_equal 3, Topic.reflect_on_all_validations.size 20 attr_names = Topic.reflect_on_all_validations.map { |v| v.name } 21 [:title,:content,:terms_of_service].each { |s| assert attr_names.include?(s) } 22 23 macro_names = Topic.reflect_on_all_validations.map { |v| v.macro } 24 assert_equal 2, macro_names.select{ |m| m == :validates_presence_of }.size 25 assert_equal 1, macro_names.select{ |m| m == :validates_acceptance_of }.size 26 end 27 28 def test_reflect_on_validations_for 29 Topic.validates_presence_of(:title, :content) 30 Topic.validates_length_of(:title, :within => 1...10) 31 32 title_validations = Topic.reflect_on_validations_for(:title) 33 assert_equal 2, title_validations.length 34 assert title_validations.find { |v| v.macro == :validates_presence_of } 35 assert title_validations.find { |v| v.macro == :validates_length_of } 36 assert !title_validations.find { |v| v.name != :title } 37 38 assert_equal 1, Topic.reflect_on_validations_for(:content).size 39 40 assert_equal [], Topic.reflect_on_validations_for(:does_not_exist) 41 end 42 43 # test whether options passed to validation macros can be recovered correctly 44 def test_reflect_options 45 Topic.validates_length_of(:title, :within => 1...10, :msg => "should be one digit") 46 47 validation = Topic.reflect_on_all_validations.first 48 assert_equal :title, validation.name 49 assert_equal 1...10, validation.options[:within] 50 assert_equal "should be one digit", validation.options[:msg] 51 end 52 53 end -
activerecord/lib/active_record/reflection.rb
old new 31 31 end 32 32 end_eval 33 33 end 34 35 for validation_type in %w( validates_presence_of validates_acceptance_of validates_length_of ) 36 base.module_eval <<-"end_eval" 37 class << self 38 alias_method :#{validation_type}_without_reflection, :#{validation_type} 39 40 def #{validation_type}_with_reflection(*attr_names) 41 #{validation_type}_without_reflection(*attr_names) 42 configuration = attr_names.last.is_a?(Hash) ? attr_names.pop : nil 43 for attr_name in attr_names 44 write_inheritable_array "validations", [ MacroReflection.new(:#{validation_type}, attr_name, configuration, self) ] 45 end 46 end 47 48 alias_method :#{validation_type}, :#{validation_type}_with_reflection 49 end 50 end_eval 51 end 34 52 end 35 53 36 54 # Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations. … … 60 78 def reflect_on_association(association) 61 79 reflect_on_all_associations.find { |reflection| reflection.name == association } unless reflect_on_all_associations.nil? 62 80 end 81 82 # Returns an array of MacroReflection objects for all validations in the class 83 def reflect_on_all_validations 84 read_inheritable_attribute "validations" 85 end 86 87 # Returns an array of MacroReflection objects for all validations defined for the field +attr_name+ (expects a symbol) 88 def reflect_on_validations_for(attr_name) 89 reflect_on_all_validations.find_all { |reflection| reflection.name == attr_name } unless reflect_on_all_validations.nil? 90 end 63 91 end 64 92 65 93 … … 128 156 return class_name || name 129 157 end 130 158 end 159 131 160 end 132 161 end -
actionpack/lib/action_view/helpers/javascript_validation_helper.rb
old new 1 require File.dirname(__FILE__) + '/form_helper' 2 3 module ActionView 4 module Helpers 5 module FormHelper 6 # method names in FormHelper that will automatically register fields for javascript validation 7 VALIDATION_FIELD_TYPES = %w(text_field password_field file_field text_area check_box radio_button) 8 9 for field_type in VALIDATION_FIELD_TYPES 10 module_eval <<-ENDEVAL 11 alias_method :#{field_type}_without_js_validation, :#{field_type} 12 13 def #{field_type}_with_js_validation(object,method,*args) 14 register_for_javascript_validation(object,method) 15 #{field_type}_without_js_validation(object,method,*args) 16 end 17 18 alias_method :#{field_type}, :#{field_type}_with_js_validation 19 ENDEVAL 20 end 21 end 22 23 module JavascriptValidationHelper 24 def register_for_javascript_validation(object_name,method_name) 25 @rails_instance_tags ||= [] 26 @rails_instance_tags << InstanceTag.new(object_name,method_name,self) 27 end 28 29 # Generate a javascript function for field validations. This will generate 30 # code to validate all fields that have been included via FormHelper methods and for 31 # which a validation with a supported validates_... macro has been defined. 32 # The javascript code returned will be wrapped in a proper +script+ tag and 33 # will be named as the value of the +function_name+ parameter (defaults to 34 # +validateForm+. 35 # To active validation before form submission, you should add the property 36 # <tt>onsubmit="return validateForm(this)"</tt> to your form tag. 37 def javascript_validation_for_fields(function_name="validateForm") 38 js_calls = @rails_instance_tags.inject([]) { |memo,tag| memo += function_names_for(tag) } 39 <<-ENDJS 40 <script type="text/javascript" language="javascript"> 41 function #{function_name}(form) { 42 return #{js_calls.join(" && ")}; 43 } 44 </script> 45 ENDJS 46 end 47 48 private 49 50 def function_names_for(instance_tag) 51 instance_tag.object.class.reflect_on_validations_for(instance_tag.method_name.to_sym). 52 inject([]) do |js_calls,validation| 53 case validation.macro 54 when :validates_presence_of 55 js_calls << "validatePresence(form['#{instance_tag.js_tag_name}'])" 56 when :validates_length_of 57 js_calls += js_validate_length(validation,instance_tag) 58 end 59 end 60 end 61 62 def js_validate_length(validation,tag) 63 js = [] 64 if validation.options[:maximum] 65 js << "validateLength(form['#{tag.js_tag_name}'],#{validation.options[:maximum]})" 66 end 67 js 68 end 69 70 end 71 end 72 end -
actionpack/lib/action_view/helpers/form_helper.rb
old new 244 244 end 245 245 end 246 246 247 def js_tag_name(options = {}) 248 add_default_name_and_id(options) 249 options["name"] 250 end 251 247 252 private 248 253 def add_default_name_and_id(options) 249 254 if options.has_key?("index")