Module: ValidationSyncFormHelper

Defined in:
app/helpers/validation_sync_form_helper.rb

Instance Method Summary collapse

Instance Method Details

#form_for(record, options = {}, &block) ⇒ Object

Override the default form_for method to include a data-sync-validations attribute, set to true / false (original found in rails/actionpack/lib/action_view/helpers/form_helper.rb) returns a string (html markup)

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/helpers/validation_sync_form_helper.rb', line 11

def form_for(record, options = {}, &block)
	raise ArgumentError, "Missing block" unless block_given?

	# Default to validate = false
	options[:validate] ||= false

	# If the html_options / data hashes are not
	# set, then let's add them as empty hashes
	options[:html] ||= {}
	options[:html][:data] ||= {}

	# Add our data-sync-validations attribute
	options[:html][:data][:sync_validations] = options[:validate].to_s

	html_options = options[:html] ||= {}

	case record
	when String, Symbol
		object_name = record
		object      = nil
	else
		object      = record.is_a?(Array) ? record.last : record
		raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
		object_name = options[:as] || model_name_from_record_or_class(object).param_key
		apply_form_for_options!(record, object, options)
	end

	html_options[:data]   = options.delete(:data)   if options.has_key?(:data)
	html_options[:remote] = options.delete(:remote) if options.has_key?(:remote)
	html_options[:method] = options.delete(:method) if options.has_key?(:method)
	html_options[:authenticity_token] = options.delete(:authenticity_token)

	builder = instantiate_builder(object_name, object, options)
	output  = capture(builder, &block)
	html_options[:multipart] ||= builder.multipart?

	# Generate our validations
	javascript_validations = javascript_tag { generate_validations(object).html_safe }

	# Inject the validation JS if :validate => true
	if options[:validate]
		output = "" if output.nil?
		form_tag(options[:url] || {}, html_options) { output + javascript_validations }
	else
		form_tag(options[:url] || {}, html_options) { output }
	end
end

#generate_messages(model_class, builder) ⇒ Object

Generate the Javascript version of this model’s validation messages returns a string (javascript code)



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'app/helpers/validation_sync_form_helper.rb', line 155

def generate_messages(model_class, builder)
	# Helpers for ActiveRecord/Model Validators
	presence_validator 			= ActiveRecord::Validations::PresenceValidator
	number_validator 				= ActiveModel::Validations::NumericalityValidator
	confirmation_validator	= ActiveModel::Validations::ConfirmationValidator

	builder.object_name = model_class.name
	messages = ""
	
	model_class.column_names.each do |attr|
		builder.method = attr.to_sym

		messages << "\"#{model_class.name.downcase}[#{attr}]\": {"

		# REQUIRED: if we use the presence_validator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(presence_validator)
			messages << "required: \"#{builder.get_validation_message(presence_validator)}\","

		# REQUIRED: if we use the ActiveModel::Validations::NumericalityValidator, :allow_nil => false
		# ----------------------------------------------------------------
		elsif builder.check_model_validation(number_validator)
			# with allow_nil = false
			if builder.get_validation_attr(number_validator, :allow_nil).nil?
				messages << "required: \"#{builder.get_validation_message(number_validator)}\","
			end
		end # REQUIRED

		# NUMBER: if we use the number_validator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(number_validator)
			messages << "number: \"#{builder.get_validation_message(number_validator)}\","
		end


		# EQUALTO: if we use the confirmation_validator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(confirmation_validator)
			messages << "equalTo: \"#{builder.get_validation_message(confirmation_validator)}\","
		end

		messages << '},'
	end

	return messages
end

#generate_rules(model_class, builder) ⇒ Object

Generate the Javascript version of this model’s validation requirements returns a string (javascript code)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/helpers/validation_sync_form_helper.rb', line 104

def generate_rules(model_class, builder)
	builder.object_name = model_class.name
	rules = ""
	
	model_class.column_names.each do |attr|
		builder.method = attr.to_sym

		rules << "\"#{model_class.name.downcase}[#{attr}]\": {"

		# REQUIRED: if we use the ActiveRecord::Validations::PresenceValidator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(ActiveRecord::Validations::PresenceValidator)
			rules << "required: true,"

		# REQUIRED: if we use the ActiveModel::Validations::NumericalityValidator, :allow_nil => false
		# ----------------------------------------------------------------
		elsif builder.check_model_validation(ActiveModel::Validations::NumericalityValidator)
			# with allow_nil = false
			if builder.get_validation_attr(ActiveModel::Validations::NumericalityValidator, :allow_nil).nil?
				rules << "required: true,"
			end
		end # REQUIRED

		# NUMBER: if we use the ActiveModel::Validations::NumericalityValidator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(ActiveModel::Validations::NumericalityValidator)
			rules << "number: true,"
		end


		# EQUALTO: if we use the ActiveModel::Validations::ConfirmationValidator	
		# ----------------------------------------------------------------
		if builder.check_model_validation(ActiveModel::Validations::ConfirmationValidator)
			rules << "equalTo: '##{model_class.name.downcase}_#{attr}_confirmation',"
		end

		rules << '},'
	end

	return rules
end

#generate_validations(object) ⇒ Object

Generate Javascript validations for a given model returns a string (javascript code)



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/helpers/validation_sync_form_helper.rb', line 69

def generate_validations(object)
	# Our Builder object
	@builder = ValidationBuilder.new

	model_class = object.class

	return <<-EOD
		var ValidationSync;

		ValidationSync = {
			init: function() {
				$forms = $(".new_#{model_class.name.downcase}, .edit_#{model_class.name.downcase}, .formtastic.#{model_class.name.downcase}");
				$forms.validate({
					rules: {
						#{generate_rules(model_class, @builder)}
					},
					messages: {
						#{generate_messages(model_class, @builder)}
					},
				})
			}
		};

		$(document).on('ready page:load', ValidationSync.init);
	EOD
end