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 "    var ValidationSync;\n\n    ValidationSync = {\n      init: function() {\n        $forms = $(\".new_\#{model_class.name.downcase}, .edit_\#{model_class.name.downcase}, .formtastic.\#{model_class.name.downcase}\");\n        $forms.validate({\n          rules: {\n            \#{generate_rules(model_class, @builder)}\n          },\n          messages: {\n            \#{generate_messages(model_class, @builder)}\n          },\n        })\n      }\n    };\n\n    $(document).on('ready page:load', ValidationSync.init);\n  EOD\nend\n"