active_form 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -0
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/MIT-LICENSE +19 -0
- data/Manifest.txt +181 -0
- data/README.txt +1 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +71 -0
- data/config/requirements.rb +17 -0
- data/init.rb +5 -0
- data/lib/active_form.rb +86 -0
- data/lib/active_form/core_extensions.rb +179 -0
- data/lib/active_form/definition.rb +72 -0
- data/lib/active_form/element.rb +50 -0
- data/lib/active_form/elements/base.rb +67 -0
- data/lib/active_form/elements/builder.rb +103 -0
- data/lib/active_form/elements/button.rb +15 -0
- data/lib/active_form/elements/checkbox.rb +18 -0
- data/lib/active_form/elements/file.rb +15 -0
- data/lib/active_form/elements/hidden.rb +9 -0
- data/lib/active_form/elements/image.rb +7 -0
- data/lib/active_form/elements/input.rb +23 -0
- data/lib/active_form/elements/password.rb +12 -0
- data/lib/active_form/elements/radio.rb +18 -0
- data/lib/active_form/elements/reset.rb +15 -0
- data/lib/active_form/elements/section.rb +37 -0
- data/lib/active_form/elements/select.rb +42 -0
- data/lib/active_form/elements/submit.rb +19 -0
- data/lib/active_form/elements/text.rb +9 -0
- data/lib/active_form/elements/textarea.rb +18 -0
- data/lib/active_form/errors.rb +73 -0
- data/lib/active_form/facets/checkbox_group.rb +11 -0
- data/lib/active_form/facets/collection_input.rb +96 -0
- data/lib/active_form/facets/radio_group.rb +11 -0
- data/lib/active_form/facets/select_date.rb +10 -0
- data/lib/active_form/facets/select_datetime.rb +10 -0
- data/lib/active_form/facets/select_day.rb +17 -0
- data/lib/active_form/facets/select_from_model.rb +60 -0
- data/lib/active_form/facets/select_hour.rb +17 -0
- data/lib/active_form/facets/select_minute.rb +17 -0
- data/lib/active_form/facets/select_month.rb +46 -0
- data/lib/active_form/facets/select_numeric_range.rb +59 -0
- data/lib/active_form/facets/select_second.rb +17 -0
- data/lib/active_form/facets/select_time.rb +10 -0
- data/lib/active_form/facets/select_timebased.rb +145 -0
- data/lib/active_form/facets/select_weekday.rb +46 -0
- data/lib/active_form/facets/select_year.rb +24 -0
- data/lib/active_form/mixins/attribute_methods.rb +33 -0
- data/lib/active_form/mixins/casting.rb +152 -0
- data/lib/active_form/mixins/collection_element_methods.rb +204 -0
- data/lib/active_form/mixins/common_methods.rb +350 -0
- data/lib/active_form/mixins/container_methods.rb +417 -0
- data/lib/active_form/mixins/css_methods.rb +70 -0
- data/lib/active_form/mixins/element_methods.rb +314 -0
- data/lib/active_form/mixins/javascript_methods.rb +99 -0
- data/lib/active_form/mixins/loader_methods.rb +72 -0
- data/lib/active_form/mixins/option_element_methods.rb +61 -0
- data/lib/active_form/mixins/validation_methods.rb +253 -0
- data/lib/active_form/validator.rb +47 -0
- data/lib/active_form/validators/alpha.rb +9 -0
- data/lib/active_form/validators/alphanum.rb +9 -0
- data/lib/active_form/validators/base.rb +132 -0
- data/lib/active_form/validators/digits.rb +9 -0
- data/lib/active_form/validators/email.rb +29 -0
- data/lib/active_form/validators/format.rb +15 -0
- data/lib/active_form/validators/length_range.rb +24 -0
- data/lib/active_form/validators/number.rb +9 -0
- data/lib/active_form/validators/option_count.rb +24 -0
- data/lib/active_form/validators/proc.rb +22 -0
- data/lib/active_form/validators/required.rb +9 -0
- data/lib/active_form/validators/set.rb +21 -0
- data/lib/active_form/validators/time_range.rb +30 -0
- data/lib/active_form/validators/uri.rb +54 -0
- data/lib/active_form/version.rb +9 -0
- data/lib/active_form/views/fieldsets.rb +34 -0
- data/lib/active_form/views/plain.rb +32 -0
- data/lib/active_form/views/tables.rb +28 -0
- data/lib/active_form/widget.rb +43 -0
- data/lib/active_form/widgets/base.rb +28 -0
- data/lib/loob/uri_validator.rb +140 -0
- data/lib/rails/acts_as_dropdown/MIT-LICENSE +20 -0
- data/lib/rails/acts_as_dropdown/acts_as_dropdown.rb +119 -0
- data/lib/rails/acts_as_dropdown/dropdown.rb +27 -0
- data/lib/rails/controller_helper.rb +19 -0
- data/lib/rails/model/loader.rb +206 -0
- data/lib/rails/view_helper.rb +20 -0
- data/samples/html/css/style.css +175 -0
- data/samples/html/js/effects.js +958 -0
- data/samples/html/js/prototype.js +2006 -0
- data/samples/html/js/validation.js +228 -0
- data/samples/html/plain_view.html +77 -0
- data/samples/html/sample001.html +158 -0
- data/samples/html/sample002.html +76 -0
- data/samples/html/sample003.html +34 -0
- data/samples/layouts/default.rhtml +18 -0
- data/samples/layouts/plain.rhtml +21 -0
- data/samples/layouts/sample003.rhtml +25 -0
- data/samples/plain_view.rb +58 -0
- data/samples/sample001.rb +111 -0
- data/samples/sample002.rb +92 -0
- data/samples/sample003.rb +30 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/elements/test_base_element.rb +159 -0
- data/test/elements/test_builder_element.rb +81 -0
- data/test/elements/test_button_element.rb +12 -0
- data/test/elements/test_checkbox_element.rb +233 -0
- data/test/elements/test_file_element.rb +20 -0
- data/test/elements/test_hidden_element.rb +11 -0
- data/test/elements/test_image_element.rb +11 -0
- data/test/elements/test_input_element.rb +39 -0
- data/test/elements/test_password_element.rb +16 -0
- data/test/elements/test_radio_element.rb +197 -0
- data/test/elements/test_reset_element.rb +12 -0
- data/test/elements/test_section_element.rb +162 -0
- data/test/elements/test_select_element.rb +364 -0
- data/test/elements/test_submit_element.rb +12 -0
- data/test/elements/test_text_element.rb +91 -0
- data/test/elements/test_textarea_element.rb +23 -0
- data/test/facets/test_checkbox_group_element.rb +388 -0
- data/test/facets/test_radio_group_element.rb +312 -0
- data/test/facets/test_select_date_element.rb +211 -0
- data/test/facets/test_select_datetime_element.rb +56 -0
- data/test/facets/test_select_day_element.rb +37 -0
- data/test/facets/test_select_from_model_element.rb +86 -0
- data/test/facets/test_select_hour_element.rb +37 -0
- data/test/facets/test_select_minute_element.rb +52 -0
- data/test/facets/test_select_month_element.rb +79 -0
- data/test/facets/test_select_numeric_range_element.rb +14 -0
- data/test/facets/test_select_second_element.rb +48 -0
- data/test/facets/test_select_time_element.rb +148 -0
- data/test/facets/test_select_weekday_element.rb +71 -0
- data/test/facets/test_select_year_element.rb +73 -0
- data/test/fixtures/author.rb +11 -0
- data/test/fixtures/authors.yml +0 -0
- data/test/fixtures/book.rb +14 -0
- data/test/fixtures/books.yml +8 -0
- data/test/fixtures/categories.yml +0 -0
- data/test/fixtures/categorization.rb +2 -0
- data/test/fixtures/categorizations.yml +0 -0
- data/test/fixtures/category.rb +8 -0
- data/test/fixtures/publisher.rb +5 -0
- data/test/fixtures/publishers.yml +10 -0
- data/test/fixtures/schema.rb +43 -0
- data/test/rails/test_model_autodefinition.rb +121 -0
- data/test/rails/test_model_loader.rb +61 -0
- data/test/resources/elements/chunky.rb +11 -0
- data/test/resources/forms/demo.rb +5 -0
- data/test/resources/models/book.rb +8 -0
- data/test/resources/models/register_publisher.rb +5 -0
- data/test/resources/sections/demo.rb +6 -0
- data/test/resources/sections/foo.rb +6 -0
- data/test/resources/validators/foo.rb +9 -0
- data/test/resources/widgets/custom.rb +13 -0
- data/test/test_active_form.rb +1050 -0
- data/test/test_casting.rb +124 -0
- data/test/test_definition.rb +68 -0
- data/test/test_definition_class.rb +118 -0
- data/test/test_element_class.rb +201 -0
- data/test/test_helper.rb +74 -0
- data/test/test_javascript.rb +234 -0
- data/test/test_load_definition.rb +68 -0
- data/test/test_load_element.rb +35 -0
- data/test/test_load_section_element.rb +43 -0
- data/test/test_load_validator.rb +31 -0
- data/test/test_load_widget.rb +93 -0
- data/test/test_validation.rb +722 -0
- data/test/validators/test_validates_as_alpha.rb +26 -0
- data/test/validators/test_validates_as_alphanum.rb +26 -0
- data/test/validators/test_validates_as_digits.rb +26 -0
- data/test/validators/test_validates_as_email.rb +29 -0
- data/test/validators/test_validates_as_number.rb +26 -0
- data/test/validators/test_validates_as_uri.rb +128 -0
- data/test/validators/test_validates_with_format.rb +26 -0
- data/test/validators/test_validates_within_length_range.rb +46 -0
- data/test/validators/test_validates_within_set.rb +46 -0
- data/test/validators/test_validates_within_time_range.rb +53 -0
- metadata +307 -0
- metadata.gz.sig +4 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module ActiveForm::Mixins::OptionElementMethods
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.define_html_flags(:checked, false)
|
5
|
+
end
|
6
|
+
|
7
|
+
def options=(val)
|
8
|
+
if val.kind_of?(Array)
|
9
|
+
self.fallback_value = val.last
|
10
|
+
self.checked_value = val.first
|
11
|
+
else
|
12
|
+
self.checked_value = val
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias :option= :options=
|
16
|
+
|
17
|
+
def checked_value=(value)
|
18
|
+
@checked_value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def checked_value
|
22
|
+
@checked_value ||= nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_option?(value)
|
26
|
+
[self.checked_value, self.fallback_value].include?(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def checked?
|
30
|
+
perform_check!
|
31
|
+
end
|
32
|
+
alias :active? :checked?
|
33
|
+
alias :selected? :checked?
|
34
|
+
|
35
|
+
def checked
|
36
|
+
self.html_flags[:checked]
|
37
|
+
end
|
38
|
+
|
39
|
+
def checked=(value)
|
40
|
+
self.html_flags[:checked] = value.to_s.to_boolean
|
41
|
+
self.element_value = (self.html_flags[:checked] ? self.checked_value : self.fallback_value)
|
42
|
+
self.html_flags[:checked]
|
43
|
+
end
|
44
|
+
|
45
|
+
def perform_check!
|
46
|
+
self.html_flags[:checked] = !self.blank? && self.element_value == self.checked_value
|
47
|
+
self.element_value = (self.html_flags[:checked] ? self.checked_value : self.fallback_value)
|
48
|
+
self.html_flags[:checked]
|
49
|
+
end
|
50
|
+
|
51
|
+
def required=(value)
|
52
|
+
self.option_flags[:required] = value.to_s.to_boolean
|
53
|
+
if self.option_flags[:required]
|
54
|
+
req = proc { |v| v.element.errors.add(v.message, 'confirm') unless v.element.checked? }
|
55
|
+
validates_with_proc :code => 'required', :proc => req
|
56
|
+
else
|
57
|
+
validators.delete_if { |v| v.code == 'required' }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
module ActiveForm::Mixins::ValidationMethods
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:extend, ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def define_validator(type, *args, &block)
|
8
|
+
args.unshift(self)
|
9
|
+
validator = ActiveForm::Validator::build(type, *args, &block)
|
10
|
+
validators << validator
|
11
|
+
validator
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_message(msg = @@default_msg, error_code = 'default', params = [])
|
15
|
+
msg = (localize(name, "validates_#{error_code}") || msg) if localized?
|
16
|
+
mparams = message_params + params
|
17
|
+
sprintf(msg || '', *mparams)
|
18
|
+
end
|
19
|
+
|
20
|
+
def message_params
|
21
|
+
[label, element_value]
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_validation_advice_wrapper
|
25
|
+
if respond_to?(:advice_wrapper)
|
26
|
+
method_to_proc(:advice_wrapper)
|
27
|
+
elsif self.class.respond_to?(:advice_wrapper)
|
28
|
+
self.class.method_to_proc(:advice_wrapper)
|
29
|
+
else
|
30
|
+
self.class.method_to_proc(:default_validation_advice_wrapper)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def validators_by_type(*types)
|
35
|
+
types.map(&:to_s)
|
36
|
+
self.validators.find_all { |v| types.include?(v.code) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def required_message=(str)
|
40
|
+
validator = self.validators_by_type('required').first
|
41
|
+
validator.message = str unless validator.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def validation_advice(builder = create_builder)
|
45
|
+
str = server_side_validation_advice(builder)
|
46
|
+
str << client_side_validation_advice(builder) if client_side?
|
47
|
+
str
|
48
|
+
end
|
49
|
+
|
50
|
+
def server_side_validation_advice(builder = create_builder, first_only = true)
|
51
|
+
element_errors(first_only).inject('') do |str, error|
|
52
|
+
attrs = { :id => "advice-#{error.identifier}-#{error.element.identifier}", :class => "validation-advice advice-#{error.code}" }
|
53
|
+
get_validation_advice_wrapper.call(builder, error, attrs)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def all_server_side_validation_advice(builder = create_builder)
|
58
|
+
server_side_validation_advice(builder, false)
|
59
|
+
end
|
60
|
+
|
61
|
+
def client_side_validation_advice(builder = create_builder)
|
62
|
+
gather_validation_advice.each do |adv|
|
63
|
+
attrs = { :id => "advice-#{adv.identifier}-#{adv.element.identifier}", :style => 'display: none', :class => "validation-advice advice-#{adv.code}" }
|
64
|
+
get_validation_advice_wrapper.call(builder, adv, attrs)
|
65
|
+
end
|
66
|
+
builder.target!
|
67
|
+
end
|
68
|
+
|
69
|
+
def gather_validation_advice
|
70
|
+
adv = validators.inject([]) { |ary, v| v.advice.keys.sort.inject(ary) { |a, key| a << v.advice[key] unless v.advice[key].blank? } }
|
71
|
+
each { |elem| adv += elem.gather_validation_advice } if container?
|
72
|
+
adv.compact
|
73
|
+
end
|
74
|
+
|
75
|
+
def validation_css_class
|
76
|
+
css = validators.inject(CssAttribute.new) { |cs, v| cs << "#{v.identifier}" }
|
77
|
+
each { |elem| css += elem.validation_css_class } if container?
|
78
|
+
css.compact
|
79
|
+
end
|
80
|
+
|
81
|
+
def validation_javascript_definitions
|
82
|
+
js = validators.inject([]) { |ary, v| ary << v.javascript_definition }.compact.join("\n")
|
83
|
+
each { |elem| js += elem.validation_javascript_definitions } if container?
|
84
|
+
js
|
85
|
+
end
|
86
|
+
|
87
|
+
def client_side?
|
88
|
+
client_side == true || (contained? && container.client_side?)
|
89
|
+
end
|
90
|
+
|
91
|
+
def client_side_options
|
92
|
+
@client_js_options ||= { :stopOnFirst => false, :useTitles => true }
|
93
|
+
end
|
94
|
+
|
95
|
+
def client_side
|
96
|
+
@client_side_validation ||= false
|
97
|
+
end
|
98
|
+
|
99
|
+
def client_side=(value)
|
100
|
+
@client_side_validation = value.to_s.to_boolean
|
101
|
+
end
|
102
|
+
|
103
|
+
def validators
|
104
|
+
@validators ||= []
|
105
|
+
end
|
106
|
+
|
107
|
+
def errors
|
108
|
+
@errors ||= ActiveForm::Errors.new(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
def element_errors(first_only = false)
|
112
|
+
elem_errors = first_only ? [errors.first] : errors.all
|
113
|
+
elements.each { |elem| elem_errors += elem.element_errors(first_only) } if container?
|
114
|
+
elem_errors.compact
|
115
|
+
end
|
116
|
+
alias :all_errors :element_errors
|
117
|
+
alias :validation_errors :element_errors
|
118
|
+
|
119
|
+
def initial_errors
|
120
|
+
element_errors(true)
|
121
|
+
end
|
122
|
+
|
123
|
+
def each_error(&block)
|
124
|
+
element_errors.each(&block)
|
125
|
+
end
|
126
|
+
|
127
|
+
def every_error(&block)
|
128
|
+
element_errors(true).each(&block)
|
129
|
+
end
|
130
|
+
alias :every_initial_error :every_error
|
131
|
+
|
132
|
+
def reset_errors!
|
133
|
+
errors.reset
|
134
|
+
end
|
135
|
+
|
136
|
+
def valid?
|
137
|
+
initial_errors.empty?
|
138
|
+
end
|
139
|
+
|
140
|
+
def validate
|
141
|
+
perform_validation && valid?
|
142
|
+
end
|
143
|
+
|
144
|
+
def validate!
|
145
|
+
return true if validate
|
146
|
+
raise ActiveForm::ValidationException
|
147
|
+
end
|
148
|
+
|
149
|
+
def perform_validation
|
150
|
+
reset_errors!
|
151
|
+
each { |elem| elem.perform_validation } if container?
|
152
|
+
validators.each(&:validate)
|
153
|
+
validate_element
|
154
|
+
after_validation_callback(self) if respond_to?(:after_validation_callback)
|
155
|
+
return true # so you can write perform_validation && valid?
|
156
|
+
end
|
157
|
+
|
158
|
+
def clear_validations!
|
159
|
+
reset_errors!
|
160
|
+
recurse(&:clear_validations!) if container?
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate_element
|
164
|
+
internal_validation(self) if respond_to?(:internal_validation)
|
165
|
+
validation_handler(self) if respond_to?(:validation_handler)
|
166
|
+
self.class.validation_handler(self) if self.class.respond_to?(:validation_handler)
|
167
|
+
end
|
168
|
+
|
169
|
+
def define_validation(prc = nil, &block)
|
170
|
+
define_singleton_method(:validation_handler, &(block_given? ? block : prc))
|
171
|
+
end
|
172
|
+
alias :validation= :define_validation
|
173
|
+
alias :validation :define_validation
|
174
|
+
|
175
|
+
def reset_validation
|
176
|
+
undefine_singleton_method(:validation_handler) rescue nil
|
177
|
+
end
|
178
|
+
|
179
|
+
def javascript_validation_code
|
180
|
+
return nil unless respond_to?(:js_validation_generator) || self.class.respond_to?(:js_validation_generator)
|
181
|
+
vparams = { :name => identifier.dasherize, :msg => "#{label}: validation failed" }
|
182
|
+
code = JavascriptAttribute.new
|
183
|
+
js_validation_generator(self, code, vparams) if respond_to?(:js_validation_generator)
|
184
|
+
self.class.js_validation_generator(self, code, vparams) if self.class.respond_to?(:js_validation_generator)
|
185
|
+
return nil if code.empty?
|
186
|
+
class_name = "validate-#{vparams[:name]}"
|
187
|
+
css_class << class_name unless container? || css_class.include?(class_name)
|
188
|
+
%|Validation.add('#{class_name}', "#{vparams[:msg]}", function (v) {\n #{code}\n});|
|
189
|
+
end
|
190
|
+
|
191
|
+
def javascript_validation(prc = nil, &block)
|
192
|
+
define_singleton_method(:js_validation_generator, &(block_given? ? block : prc))
|
193
|
+
end
|
194
|
+
alias :javascript_validation= :javascript_validation
|
195
|
+
|
196
|
+
def reset_javascript_validation
|
197
|
+
undefine_singleton_method(:js_validation_generator) rescue nil
|
198
|
+
end
|
199
|
+
|
200
|
+
def validation_advice_wrapper(prc = nil, &block)
|
201
|
+
define_singleton_method(:advice_wrapper, &(block_given? ? block : prc))
|
202
|
+
end
|
203
|
+
alias :javascript_validation= :javascript_validation
|
204
|
+
|
205
|
+
def reset_validation_advice_wrapper
|
206
|
+
undefine_singleton_method(:advice_wrapper) rescue nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def after_validation(prc = nil, &block)
|
210
|
+
define_singleton_method(:after_validation_callback, &(block_given? ? block : prc))
|
211
|
+
end
|
212
|
+
alias :after_validation_callback= :after_validation
|
213
|
+
|
214
|
+
def reset_after_validation_callback
|
215
|
+
undefine_singleton_method(:after_validation_callback) rescue nil
|
216
|
+
end
|
217
|
+
|
218
|
+
module ClassMethods
|
219
|
+
|
220
|
+
def define_validation(prc = nil, &block)
|
221
|
+
define_singleton_method(:validation_handler, &(block_given? ? block : prc))
|
222
|
+
end
|
223
|
+
alias :validation= :define_validation
|
224
|
+
|
225
|
+
def reset_validation
|
226
|
+
undefine_singleton_method(:validation_handler) rescue nil
|
227
|
+
end
|
228
|
+
|
229
|
+
def javascript_validation(prc = nil, &block)
|
230
|
+
define_singleton_method(:js_validation_generator, &(block_given? ? block : prc))
|
231
|
+
end
|
232
|
+
alias :javascript_validation= :javascript_validation
|
233
|
+
|
234
|
+
def reset_javascript_validation
|
235
|
+
undefine_singleton_method(:js_validation_generator) rescue nil
|
236
|
+
end
|
237
|
+
|
238
|
+
def default_validation_advice_wrapper(builder, error, attrs)
|
239
|
+
builder.div(error.message, attrs)
|
240
|
+
end
|
241
|
+
|
242
|
+
def validation_advice_wrapper(prc = nil, &block)
|
243
|
+
define_singleton_method(:advice_wrapper, &(block_given? ? block : prc))
|
244
|
+
end
|
245
|
+
alias :javascript_validation= :javascript_validation
|
246
|
+
|
247
|
+
def reset_validation_advice_wrapper
|
248
|
+
undefine_singleton_method(:advice_wrapper) rescue nil
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveForm::Validator
|
2
|
+
|
3
|
+
include ActiveForm::Mixins::LoaderMethods
|
4
|
+
|
5
|
+
class NoElemException < StandardError #:nodoc:
|
6
|
+
end
|
7
|
+
|
8
|
+
class MismatchException < StandardError #:nodoc:
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def validator?(klass)
|
14
|
+
klass < ActiveForm::Validator::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
# loader related
|
18
|
+
|
19
|
+
def load_paths
|
20
|
+
@@load_paths ||= [*base_load_paths]
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_load_paths
|
24
|
+
[::File.join(ActiveForm::BASE_PATH, 'validators')]
|
25
|
+
end
|
26
|
+
|
27
|
+
def instance(definition_name, klass, *args, &block)
|
28
|
+
item = klass.new(*args, &block)
|
29
|
+
item
|
30
|
+
end
|
31
|
+
|
32
|
+
def create(definition_name, &block)
|
33
|
+
ActiveForm::Validator::Base::create(definition_name, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def register(elem_class)
|
37
|
+
if validator?(elem_class) && !self.methods.include?("validates_#{elem_class.loadable_type}")
|
38
|
+
self.module_eval("
|
39
|
+
def validates_#{elem_class.loadable_type}(*args, &block)
|
40
|
+
define_validator(:#{elem_class.loadable_type}, *args, &block)
|
41
|
+
end")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
class ActiveForm::Validator::Base
|
2
|
+
|
3
|
+
attr_reader :element
|
4
|
+
attr_accessor :msg, :code
|
5
|
+
|
6
|
+
def initialize(*args, &block)
|
7
|
+
setup
|
8
|
+
props = args.last.is_a?(Hash) ? args.pop : {}
|
9
|
+
register_element(args.shift) if is_element?(args.first)
|
10
|
+
self.code = self.class.to_s.demodulize.underscore
|
11
|
+
props.each { |prop, value| send("#{prop}=", value) if respond_to?("#{prop}=") }
|
12
|
+
yield self if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
alias :name :code
|
16
|
+
|
17
|
+
def setup
|
18
|
+
end
|
19
|
+
|
20
|
+
def identifier
|
21
|
+
self.code == 'required' ? code : "validate-#{code}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def javascript_definition
|
25
|
+
self.class.javascript_definition(identifier)
|
26
|
+
end
|
27
|
+
|
28
|
+
def advice
|
29
|
+
{ code => ActiveForm::Error.new(element, message, code, message_params) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate
|
33
|
+
element.errors << advice[code]
|
34
|
+
end
|
35
|
+
|
36
|
+
def register_element(elem)
|
37
|
+
@element = elem
|
38
|
+
end
|
39
|
+
|
40
|
+
def code=(str)
|
41
|
+
@code = str.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def message
|
45
|
+
self.msg || self.class.message
|
46
|
+
end
|
47
|
+
|
48
|
+
def message=(str)
|
49
|
+
self.msg = str
|
50
|
+
end
|
51
|
+
|
52
|
+
def message_params
|
53
|
+
[]
|
54
|
+
end
|
55
|
+
|
56
|
+
def label
|
57
|
+
element.label
|
58
|
+
end
|
59
|
+
|
60
|
+
def value
|
61
|
+
element.element_value
|
62
|
+
end
|
63
|
+
|
64
|
+
def value_length
|
65
|
+
str = self.value.to_s
|
66
|
+
charlength = str.respond_to?(:chars) ? str.chars.length : str.length
|
67
|
+
end
|
68
|
+
|
69
|
+
def collection_length
|
70
|
+
[*self.value].delete_if { |v| v.blank? }.length
|
71
|
+
end
|
72
|
+
|
73
|
+
def is_element?(arg)
|
74
|
+
arg.respond_to?(:element?) && arg.element?
|
75
|
+
end
|
76
|
+
|
77
|
+
def js_validation(validation_msg, code)
|
78
|
+
end
|
79
|
+
|
80
|
+
class << self
|
81
|
+
|
82
|
+
def javascript_validation(msg = 'validation failed', jscode = '')
|
83
|
+
self.javascript_validation_code = { :msg => msg, :jscode => yield(jscode) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def javascript_definition(identifier)
|
87
|
+
return nil if self.javascript_validation_code.blank?
|
88
|
+
%|Validation.add('#{identifier}', "#{self.javascript_validation_code[:msg]}", function (v) {\n #{self.javascript_validation_code[:jscode]}\n});|
|
89
|
+
end
|
90
|
+
|
91
|
+
def message
|
92
|
+
self.default_msg ||= '%s: validation failure'
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_message=(str)
|
96
|
+
self.default_msg = str
|
97
|
+
end
|
98
|
+
alias :default_message :default_message=
|
99
|
+
|
100
|
+
def inherited(derivative)
|
101
|
+
ActiveForm::Validator::register(derivative) if derivative.kind_of?(ActiveForm::Validator::Base)
|
102
|
+
derivative.class_inheritable_accessor :default_msg
|
103
|
+
derivative.class_inheritable_accessor :javascript_validation_code
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
107
|
+
def create(definition_name, &block)
|
108
|
+
class_name = name_to_class_name(definition_name)
|
109
|
+
if !ActiveForm::Validator.const_defined?(class_name)
|
110
|
+
ActiveForm::Validator.const_set(class_name, Class.new(self))
|
111
|
+
if klass = ActiveForm::Validator.const_get(class_name)
|
112
|
+
klass.module_eval(&block) if block_given?
|
113
|
+
ActiveForm::Validator::register(klass)
|
114
|
+
return klass
|
115
|
+
end
|
116
|
+
end
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
def loadable_type
|
121
|
+
self.name.to_s.demodulize.underscore.to_sym
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def name_to_class_name(definition_name)
|
127
|
+
Inflector::camelize("#{definition_name}")
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|