Module: Formbuilder::Entry

Extended by:
ActiveSupport::Concern
Defined in:
lib/formbuilder/entry.rb

Instance Method Summary collapse

Instance Method Details

#audit_responsesObject

case response_field.field_type

  when 'website'
    unless value[/^http:\/\//] || value[/^https:\/\//]
      save_response("http://#{value}", response_field)
    end
  end
end

end



205
206
207
208
209
# File 'lib/formbuilder/entry.rb', line 205

def audit_responses
  form.response_fields.each do |response_field|
    response_field.audit_response(self.response_value(response_field), self.responses)
  end
end

#calculate_additional_infoObject



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/formbuilder/entry.rb', line 172

def calculate_additional_info
  response_fieldable.response_fields.reject { |rf| !rf.input_field }.each do |response_field|
    value = response_value(response_field)
    next unless value.present?

    case response_field.field_type
    when 'address'
      begin
        coords = Geocoder.coordinates("#{value['street']} #{value['city']} #{value['state']} #{value['zipcode']} #{value['country']}")
        self.responses["#{response_field.id}_x"] = coords[0]
        self.responses["#{response_field.id}_y"] = coords[1]
      rescue
        self.responses["#{response_field.id}_x"] = nil
        self.responses["#{response_field.id}_y"] = nil
      end
    end
  end
end

#calculate_responses_textObject



157
158
159
160
161
# File 'lib/formbuilder/entry.rb', line 157

def calculate_responses_text
  return unless self.respond_to?(:"responses_text=")
  selected_responses = self.responses.select { |k, v| Integer(k) rescue nil }
  self.responses_text = selected_responses.values.join(' ')
end

#calculate_sortable_value(response_field, value) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/formbuilder/entry.rb', line 211

def calculate_sortable_value(response_field, value)
  return unless value.present?

  self.responses["#{response_field.id}_sortable_value"] = case response_field.field_type
  when "date"
    ['year', 'month', 'day'].each { |x| return 0 unless value[x] && !value[x].blank? }
    DateTime.new(value['year'].to_i, value['month'].to_i, value['day'].to_i).to_i rescue 0
  when "time"
    hours = value['hours'].to_i
    hours += 12 if value['am_pm'] && value['am_pm'] == 'PM'
    (hours*60*60) + (value['minutes'].to_i * 60) + value['seconds'].to_i
  when "file"
    value ? 1 : 0
  when "checkboxes"
    calculate_sortable_value_for_checkboxes(response_field, value)
    return nil
  when "price"
    "#{value['dollars'] || '0'}.#{value['cents'] || '0'}".to_f
  else
    # do we really need to sort more than the first 10 characters of a string?
    value[0..10]
  end
end

#calculate_sortable_value_for_checkboxes(response_field, value) ⇒ Object



235
236
237
238
239
# File 'lib/formbuilder/entry.rb', line 235

def calculate_sortable_value_for_checkboxes(response_field, value)
  (response_field.field_options['options'] || []).each do |option|
    self.responses["#{response_field.id}_sortable_values_#{option['label']}"] = value[option['label']]
  end
end

#calculate_sortable_valuesObject

useful when migrating



164
165
166
167
168
169
170
# File 'lib/formbuilder/entry.rb', line 164

def calculate_sortable_values
  response_fieldable.response_fields.reject { |rf| !rf.input_field }.each do |response_field|
    calculate_sortable_value(response_field, response_value(response_field))
  end

  self.responses_will_change! # hack to make sure column is marked as dirty
end

#destroy_response(response_field) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/formbuilder/entry.rb', line 135

def destroy_response(response_field)
  case response_field.field_type
  when "file"
    self.remove_entry_attachment(responses[response_field.id.to_s])
  end

  id = response_field.id.to_s
  new_responses = self.responses.reject { |k, v| k.in?([id, "#{id}_sortable_value"]) }
  self.responses = new_responses

  self.responses_will_change! # hack to make sure column is marked as dirty
end

#error_for(response_field) ⇒ Object



153
154
155
# File 'lib/formbuilder/entry.rb', line 153

def error_for(response_field)
  (self.errors.messages[:"responses_#{response_field.id}"] || [])[0]
end

#remove_entry_attachment(entry_attachment_id) ⇒ Object



148
149
150
151
# File 'lib/formbuilder/entry.rb', line 148

def remove_entry_attachment(entry_attachment_id)
  return unless entry_attachment_id.present?
  EntryAttachment.where(id: entry_attachment_id).first.try(:destroy)
end

#response_value(response_field) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/formbuilder/entry.rb', line 57

def response_value(response_field)
  value = responses && responses[response_field.id.to_s]

  if value
    response_field.serialized ? YAML::load(value) : value
  elsif !value && response_field.serialized && response_field.field_type != 'checkboxes'
    {}
  else # for checkboxes, we need to know the difference between no value and none selected
    nil
  end
end

#save_response(raw_value, response_field, response_field_params = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
# File 'lib/formbuilder/entry.rb', line 78

def save_response(raw_value, response_field, response_field_params = {})
  value = case response_field.field_type
  when "checkboxes"
    # transform checkboxes into {label => on/off} pairs
    values = {}

    (response_field[:field_options]["options"] || []).each_with_index do |option, index|
      label = response_field.field_options["options"][index]["label"]
      values[option["label"]] = raw_value && raw_value[index.to_s] == "on"
    end

    if raw_value && raw_value['other_checkbox'] == 'on'
      values['Other'] = raw_value['other']
    else
      values.delete('Other') # @todo this might cause unexpected behavior to the user. we should hide/show the other field in the frontend, too
    end

    # Save 'other' value
    responses["#{response_field.id}_other"] = raw_value && raw_value['other_checkbox'] == 'on' ?
                                                true :
                                                nil

    values

  when "file"
    # if the file is already uploaded and we're not uploading another,
    # be sure to keep it
    if raw_value.blank?
      if old_responses && old_responses[response_field.id.to_s]
        old_responses[response_field.id.to_s]
      end
    else
      remove_entry_attachment(responses[response_field.id.to_s]) if responses
      attachment = EntryAttachment.create(upload: raw_value)
      attachment.id
    end
  when "radio"
    # Save 'other' value
    responses["#{response_field.id}_other"] = raw_value == 'Other' ?
                                                response_field_params["#{response_field.id}_other"] :
                                                nil

    raw_value
  else
    raw_value
  end

  self.responses ||= {}

  if value.present?
    self.responses["#{response_field.id}"] = response_field.serialized ? value.to_yaml : value
    calculate_sortable_value(response_field, value)
  end

  self.responses_will_change! # hack to make sure column is marked as dirty
end

#save_responses(response_field_params, response_fields) ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/formbuilder/entry.rb', line 69

def save_responses(response_field_params, response_fields)
  self.old_responses = self.responses.try(:clone) || {}
  self.responses = {}

  response_fields.reject { |rf| !rf.input_field }.each do |response_field|
    self.save_response(response_field_params.try(:[], response_field.id.to_s), response_field, response_field_params)
  end
end

#submit!(skip_validation = false) ⇒ Object



13
14
15
16
17
18
19
20
21
22
# File 'lib/formbuilder/entry.rb', line 13

def submit!(skip_validation = false)
  return false if !skip_validation && !valid?

  self.audit_responses

  self.update_attributes(
    submitted_at: Time.now,
    skip_validation: true # don't validate twice
  )
end

#submitted?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/formbuilder/entry.rb', line 31

def 
  self..present?
end

#unsubmit!Object



24
25
26
27
28
29
# File 'lib/formbuilder/entry.rb', line 24

def unsubmit!
  self.update_attributes(
    submitted_at: nil,
    skip_validation: true
  )
end

#value_present?(response_field) ⇒ Boolean

Returns:

  • (Boolean)


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/formbuilder/entry.rb', line 35

def value_present?(response_field)
  value = self.response_value(response_field)

  # value isn't blank (ignore hashes)
  return true if (value && value.present? && !value.is_a?(Hash))

  # no options are available
  return true if (response_field.options_field && Array(response_field.field_options["options"]).empty?)

  # there is at least one value (for hashes)
  # reject select fields
  return true if (value.is_a?(Hash) && value.reject { |k, v| k.in? ['am_pm', 'country'] }.find { |k, v| v.present? })

  # otherwise, it's not present
  return false
end

#value_present_or_checkboxes?(response_field) ⇒ Boolean

checkboxes can have no values, yet still need to show up as unchecked

Returns:

  • (Boolean)


53
54
55
# File 'lib/formbuilder/entry.rb', line 53

def value_present_or_checkboxes?(response_field)
  response_field.field_type == 'checkboxes' || value_present?(response_field)
end