So I have a form I'm trying to submit that keeps getting jammed with a Deprecation Warning that I have posted on this SO question...
Someone was kind enough to point me in the general direction of what to do. Now I'm trying to figure out how or where the contact needs a .id attached to it. Here is my controller code associated with the problem followed by two models, one for the assignments and one for the contact.
So the ask is. where/what change must I make to resolve this Deprecation Warning ?(originally posted on the SO link above)
Processing by AssignmentsController#create as JS
Parameters: {"utf8"=>"✓", "volunteer_task_type_id"=>"41", "roster_id"=>"7", "program_id"=>"9", "set_description"=>["fonso nov5 test"], "set_date"=>["2021-01-05"], "assignment"=>{"start_time(1i)"=>"2021", "start_time(2i)"=>"11", "start_time(3i)"=>"6", "start_time(4i)"=>"08", "start_time(5i)"=>"00", "end_time(1i)"=>"2021", "end_time(2i)"=>"11", "end_time(3i)"=>"6", "end_time(4i)"=>"09", "end_time(5i)"=>"00", "notes"=>"nov5", "contact_id"=>"166574", "closed"=>"1", "lock_version"=>"0"}, "contact_element_prefix"=>"contact", "commit"=>"Submit"}
Contact Load (0.2ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = $1 LIMIT $2 [["id", 166574], ["LIMIT", 1]]
(0.2ms) BEGIN
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `exists?`. Please pass the id of the object by calling `.id`. (called from block in create at /home/fonso/back-experiment/app/controllers/assignments_controller.rb:35)
Contact Exists (0.4ms) SELECT 1 AS one FROM "contacts" WHERE "contacts"."id" = $1 LIMIT $2 [["id", 166574], ["LIMIT", 1]]
(0.2ms) ROLLBACK
Rendering assignments/new.html.erb within layouts/application
VolunteerTaskType Load (0.6ms) SELECT "volunteer_task_types".* FROM "volunteer_task_types" WHERE "volunteer_task_types"."instantiable" = $1 AND ((effective_on IS NULL OR effective_on <= '2021-11-05') AND (ineffective_on IS NULL OR ineffective_on > '2021-11-05')) [["instantiable", "t"]]
Roster Load (0.4ms) SELECT "rosters".* FROM "rosters"
assignments controller
class AssignmentsController < ApplicationController
before_action :set_assignment, only: [:show, :edit, :update, :destroy]
skip_before_action :verify_authenticity_token #TODO refactor this line to be very specific
# GET /assignments or /assignments.json
def index
# @assignments = Assignment.limit(20)
# @assignments = Assignment.where(start: params[:start]..params[:end])
@assignments = Assignment.date_range(params[:start]..params[:end])
end
# GET /assignments/1 or /assignments/1.json
def show
end
# GET /assignments/new
def new
@assignment = Assignment.new
@my_url = {:action => "create", :id => params[:id]}
end
# GET /assignments/1/edit
def edit
end
# POST /assignments or /assignments.json
def create
@assignment = Assignment.new(assignment_params)
# error wants contact.id not contact_id ???
respond_to do |format|
if @assignment.save <-------THIS IS LINE 35
format.html { redirect_to @assignment, notice: "Assignment was successfully created." }
format.json { render :show, status: :created, location: @assignment }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @assignment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /assignments/1 or /assignments/1.json
def update
@assignment.update(assignment_params)
end
# DELETE /assignments/1 or /assignments/1.json
def destroy
@assignment.destroy
# NOTE: comment original out 4 now
# respond_to do |format|
# format.html { redirect_to assignments_url, notice: "Assignment was successfully destroyed." }
# format.json { head :no_content }
# end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_assignment
@assignment = Assignment.find(params[:id])
end
# Only allow a list of trusted parameters through.
def assignment_params
params.require(:assignment).permit(:title,:redirect_to, :set_date, :date_range, :volunteer_shift_id, :contact_id, :start_time, :end_time, :start, :end, :attendance_type_id, :notes, :call_status_type_id, :closed, :lock_version, :color)
end
end
assignment Model
class Assignment < ApplicationRecord
belongs_to :volunteer_shift
has_one :volunteer_task_type, :through => :volunteer_shift, :source => :volunteer_task_type
belongs_to :contact
validates_presence_of :volunteer_shift
validates_associated :volunteer_shift
belongs_to :attendance_type
belongs_to :call_status_type
validates_presence_of :set_date, :if => :volshift_stuck
validates_existence_of :contact, :allow_nil => true
accepts_nested_attributes_for :volunteer_shift
#fixme: Nodule::DelegationError -
# This error appears when trying to show the "Add New Assignment" model on the /assignments view
delegate :set_date, :set_date=, :to => :volunteer_shift
delegate :set_description, :set_description=, :to => :volunteer_shift
scope :date_range, lambda { |range|
joins(volunteer_shift: :volunteer_event)
.where(volunteer_shifts: { volunteer_events: { date: range } })
}
scope :is_after_today, lambda {||
{ :conditions => ['(SELECT date FROM volunteer_events WHERE id = (SELECT volunteer_event_id FROM volunteer_shifts WHERE id = assignments.volunteer_shift_id)) > ?', Date.today] }
}
scope :on_or_after_today, lambda {||
{ :conditions => ['(SELECT date FROM volunteer_events WHERE id = (SELECT volunteer_event_id FROM volunteer_shifts WHERE id = assignments.volunteer_shift_id)) >= ?', Date.today] }
}
scope :not_cancelled, -> { where('(attendance_type_id IS NULL OR attendance_type_id NOT IN (SELECT id FROM attendance_types WHERE cancelled = \'t\'))')}
scope :roster_is_limited_by_program, -> {where("roster_id IN (SELECT id FROM rosters WHERE limit_shift_signup_by_program = 't')").joins(:volunteer_shift)}
attr_accessor :attendance_type_id
#fixme: fix all red dots on this page
def real_programs
return [] unless self.volunteer_shift&.roster
return [] unless self.volunteer_shift.roster.limit_shift_signup_by_program
self.volunteer_shift.roster.skeds.select{|x| x.category_type == "Program"}.map{|x| x.name}
end
# TODO: find all time_range_s methods and either pull out to DRY or give unique names
def time_range_s
return "" unless start_time and end_time
(start_time.strftime("%I:%M") + ' - ' + end_time.strftime("%I:%M")).gsub( ':00', '' ).gsub( ' 0', ' ').gsub( ' - ', '-' ).gsub(/^0/, "")
end
def description
self.volunteer_shift.volunteer_event.date.strftime("%D") + " " + self.time_range_s + " " + self.slot_type_desc
end
def roster_title
self.volunteer_shift.roster.name
end
#fixme: date / set_date is fracked since old code was ported over
def date
volunteer_shift.date
end
#full calendar uses this method name....see the assignment.json.jbuilder
def event_date
self.date
end
def slot_type_desc
b = (self.volunteer_shift.volunteer_task_type_id.nil? ? self.volunteer_shift.volunteer_event.description : self.volunteer_shift.volunteer_task_type.description)
b = b + " (#{self.volunteer_shift.description})" if self.volunteer_shift.description and self.volunteer_shift.description.length > 0
b
end
def display_name
((!(self.volunteer_shift.description.nil? or self.volunteer_shift.description.blank?)) ? self.volunteer_shift.description + ": " : "") + self.contact_display
end
def cancelled?
(self.attendance_type&.cancelled)
end
def attended?
(self.attendance_type and !self.attendance_type.cancelled)
end
def contact_display
if self.closed
"(closed)"
elsif contact_id.nil?
return "(available)"
else
self.contact.display_name + "(#{self.voltask_count})"
end
end
def <=>(other)
self.date <=> other.date
end
def contact_id=(new_val)
self.write_attribute(:contact_id, new_val)
self.contact = Contact.find_by_id(new_val.to_i)
end
def contact_id_and_by_today
# Unless the contact id is empty, or the event date is after today.
!(contact_id.nil? || self.volunteer_shift.volunteer_event.date > Date.today)
end
def voltask_count
self.contact_volunteer_task_type_count ? self.contact_volunteer_task_type_count.attributes["count"] : 0
end
before_validation :set_values_if_stuck
def set_values_if_stuck
return unless volshift_stuck
volunteer_shift.set_values_if_stuck(self)
end
after_destroy { |record| if record.volunteer_shift&.stuck_to_assignment; record.volunteer_shift.destroy; else VolunteerShift.find_by_id(record.volunteer_shift_id).fill_in_available; end}
after_save {|record| if record.volunteer_shift&.stuck_to_assignment; record.volunteer_shift.save; end}
after_save { |record| VolunteerShift.find_by_id(record.volunteer_shift_id).fill_in_available }
# def volunteer_shift_attributes=(attrs) #fixme: why is this not getting called on volunteer_events/create_shift?
# self.volunteer_shift.attributes=(attrs) # just pass it up
# end
#fixme: where is stuck_to_assignment ??? WTF?
def volshift_stuck
self.volunteer_shift&.stuck_to_assignment
end
def first_time_in_area?
if self.contact and self.volunteer_shift and self.volunteer_shift.volunteer_task_type
!ContactVolunteerTaskTypeCount.has_volunteered?(self.contact_id, self.volunteer_shift.volunteer_task_type_id)
else
false
end # and self.contact_id_changed? moved outside because we use update_attributes
end
#for fullcalendar
def all_day_event?
self.start_time == self.start_time.midnight && self.end_time == self.end_time.midnight ? true : false
end
end
Contact model
class Contact < ApplicationRecord
belongs_to :contract
has_many :assignments
has_many :contact_types_contacts
has_many :contact_types, :through => :contact_types_contacts
has_many :contact_methods
has_many :contact_method_types, :through => :contact_methods
has_many :volunteer_tasks, -> {order 'date_performed DESC'}
has_many :volunteer_task_types, :through => :volunteer_tasks
has_many :builder_tasks
has_many :disciplinary_actions, :autosave => true
# TODO: do these two even work?
def future_shifts
self.assignments.on_or_after_today.not_cancelled.sort{|a,b| t = a.date <=> b.date; t == 0 ? a.start_time <=> b.start_time : t}
end
def scheduled_shifts
a = future_shifts
more = false
if a.length > 5
a = a[0,5]
more = true
end
a = a.map{|x| x.description}
a << "More.." if more # FIXME: this needs to be a link
a.join("<br/>")
end
def is_organization?
self.is_organization
end
def is_person?
! self.is_organization?
end
def mailing_list_email
list = ContactMethodType.email_types_ordered.map{|x| x.id}
list = list.reverse if self.is_organization?
result = self.contact_methods.select{|x| x.ok}.select{|x| list.include?(x.contact_method_type_id)}.sort{|a,b| r = (list.index(a.contact_method_type_id) <=> list.index(b.contact_method_type_id)); r == 0 ? ((b.updated_at || b.created_at) <=> (a.updated_at || a.created_at)) : r}.first
result ? result.value : nil
end
# used to find when a volunteer is scheduled for more than 2 shifts
def schedule_counts
h = {}
return h if self.is_organization? # organizations may schedule as much as they like
assns = self.assignments.is_after_today.roster_is_limited_by_program.not_cancelled
assns.each do |a|
progs = a.real_programs
progs.each do |p|
h[p] ||= 0
h[p] += 1
end
end
h
end
def date_of_last_adoption
last_adoption = Disbursement.where("(disbursement_type_id = ? OR disbursement_type_id = ?) AND contact_id = ?", DisbursementType.find_by_name("adoption").id, DisbursementType.find_by_name("build").id, id).order("disbursed_at DESC").first
if last_adoption
return Date.parse(last_adoption.disbursed_at.to_s)
else
return nil
end
end
def spec_sheets_since_last_adoption(action_name)
BuilderTask.all.where("contact_id = ? AND builder_tasks.created_at > ? AND cashier_signed_off_by IS NOT NULL AND action_id = ?", self.id, date_of_last_adoption || Date.parse("2000-01-01"), Action.find_by_name(action_name).id)
end
def phone_numbers
a = []
contact_methods.map {|x|
a << x.value if (x.contact_method_type.description =~ /phone|fax/ and !(x.contact_method_type.description =~ /emergency/) and x.ok == true) # TODO: does ruby support negative lookbehinds?
}
a
end
def phone_number
phone_numbers.first
end
def has_areas_disciplined_from?
self.areas_disciplined_from.length > 0
end
def areas_disciplined_from
self.disciplinary_actions.not_disabled.map(&:disciplinary_action_areas).flatten.uniq.sort_by(&:name)
end
def find_volunteer_tasks(cutoff = nil, klass = VolunteerTask, contact_id_type = "", date_field = "date_performed", max = nil)
# if it's named volunteer_tasks it breaks everything
contact_id_type = contact_id_type + "_" if contact_id_type.length > 0
if max and cutoff
conditions = [ "#{contact_id_type}contact_id = ? AND #{date_field} > ? AND #{date_field} < ?", id, cutoff, max ]
elsif cutoff
conditions = [ "#{contact_id_type}contact_id = ? AND #{date_field} > ?", id, cutoff ]
elsif max
conditions = [ "#{contact_id_type}contact_id = ? AND #{date_field} < ?", id, max ]
else
conditions = [ "#{contact_id_type}contact_id = ?", id ]
end
klass.find(:all, :conditions => conditions)
end
def last_ninety_days_of_volunteer_tasks
find_volunteer_tasks(Date.today - Default['days_for_discount'].to_f)
end
def last_ninety_days_of_effective_hours
last_ninety_days_of_volunteer_tasks.inject(0.0) {|tot,task|
tot + task.duration
}
end
def has_worker?
! self.worker.nil? && worker.effective_now?
end
def default_discount_schedule
if self.has_worker?
return "staff"
elsif last_ninety_days_of_effective_hours >= Default['hours_for_discount'].to_f
return "volunteer"
else
return "no_discount"
end
end
def sorted_contact_methods
ContactMethodType.sort_methods(contact_methods)
end
def display_name
if is_person?
if(self.first_name || self.middle_name || self.surname)
"%s %s %s" % [self.first_name, self.middle_name, self.surname]
else
'(person without name)'
end
else
if self.organization && ! self.organization.empty?
self.organization
else
'(organization without name)'
end
end
end
end
Side note: much of this code is inherited and I'm trying to port / update it to Rails 5 (reasons).
UPDATE: adding view files
Here is the modal
<div class="modal fade" id="add_event">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<div class="col-sm-12 left ">
<h4 class="modal-title">Add New Assignment - _new.html.erb</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
</div>
<%= @my_url.inspect %>
<%= render 'assignments/form', assignment: @assignment %>
</div>
</div>
</div>
And the _form.html.erb called by the modal
<%= form_for @assignment, :url => @my_url, remote: true do |f| %>
<div class="">
<div class="modal-body d-flex">
<div class="col-sm-8 border-right">
<section id="location-date-time-notes" class="flex">
<% if @assignment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@assignment.errors.count, "error") %> prohibited this assignment from being saved:</h2>
<ul>
<% @assignment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<!-- set variable values for use later-->
<%# is_r = false %>
<!--this will never exist in this case-->
<%# shift = is_r ? f.object.volunteer_shift : f.object.volunteer_default_shift %>
<%# event = is_r ? shift.volunteer_event : shift.volunteer_default_event %>
<%# resources = is_r ? event.resources_volunteer_events : event.resources_volunteer_default_events %>
<%#= binding.pry %>
<%# assigns = is_r ? shift.assignments : shift.default_assignments %>
<%# if !is_r; assigns = assigns.select{|x| x.slot_number == f.object.slot_number}; end %>
<%# my_date = is_r ? shift.date : event.weekday.name %>
<!--VOLUNTEER SHIFT-->
<!--TODO: make this a partial-->
<div class="name large flex-row">
<%= f.label :volunteer_shift %>
</div>
<div id="volunteer_shift" class="d-flex flex-row">
<div class="col-sm-12 p-2">
<div id="volunteer_shift" class="text-right">
<!-- if class is assignment show volunteer shift else show default shift -->
<%#= f.label :volunteer_shift %>
<div class="field">
<%= f.label :volunteer_task_type_id %>
<%= select_tag 'volunteer_task_type_id', options_from_collection_for_select([VolunteerTaskType.new(:description => ""), VolunteerTaskType.instantiables.effective_on(Date.today)].flatten, "id", "description") %>
</div>
<div class="field">
<%= f.label :roster_id %>
<%= select_tag 'roster_id', options_from_collection_for_select([Roster.new(:name => ""), Roster.all].flatten, "id", "name") %>
</div>
<div class="field">
<%= f.label :program_id %>
<%= select_tag 'program_id', options_from_collection_for_select([Program.new(:name => ""), Program.where(:volunteer => true)].flatten, "id", "name")%>
</div>
<div class="field">
<%= f.label :set_description %>
<%= text_field(:set_description, nil) %>
</div>
<div class="field">
<%= f.label :set_date, "Date" %> <
<%= text_field(:set_date, nil) %>
</div>
</div>
</div>
</div>
<!--TODO: Volunteer Shift end -->
<%#= f.hidden_field :redirect_to, :value => @referer %>
<div id="time-row" class="d-flex flex-row">
<label for="assignment_time" class="col-sm-3 p-2">
<i class="fa fa-clock-o fa-lg" aria-hidden="true"></i> Time:
</label>
<div class="col- p-2">
<div class="myStartTime" id="start_time_<%= assignment.id %>">
<%= f.time_select :start_time %>
</div>
</div>
<div class="col- p-2"><i class="fa fa-arrows-h fa-lg" aria-hidden="true"></i></div>
<div class="col-sm-3 p-2">
<div class="myEndTime" id="end_time_<%= assignment.id %>">
<%= f.time_select :end_time %>
</div>
</div>
</div>
<div class="d-flex flex-row">
<label for="assignment_notes" class="col-sm-3 p-2">
<i class="fa fa-clipboard fa-lg" aria-hidden="true"></i> Notes:
</label>
<div class="col-sm-9 p-2">
<div class="d-flex flex-row">
<span> Notes only get saved if a contact is assigned the shift, and get removed when the contact is removed from the shift.</span>
<div class="">
<%= f.label :notes %>
<%= f.text_area :notes %>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="col-sm-4">
<!-- Contact Section-->
<div id="contact_section">
<% if @assigned_contacts && @assigned_contacts.length > 0 %>
<h2>Previously Assigned Contacts</h2>
<% @assigned_contacts.each do |c| %>
<%= label_tag "assigned_contacts[#{c.id}]", "Are you sure you want to remove the currently scheduled volunteer, #{c.display_name} (##{c.id}), from the assignment(s)?" %>
<%= check_box_tag "assigned_contacts[#{c.id}]", "replace", @replaced_contacts.include?(c.id) %>
<% end %>
<% end %>
<input id="contact_element_prefix" name="contact_element_prefix" type="hidden" value="contact">
<div class="name large flex-row">
<%= f.label :contact_id %><%= f.text_field :contact_id %>
</div>
<div id="display-contact" class="d-flex flex-row">
<% if f.object.contact_id %>
<%= render partial: 'contacts/display', locals: {contact:f.object.contact} %>
<% else %>
<%#= link_to 'Show Contact', contact_path(f.object.contact_id), remote: true %>
<% end %>
</div>
<!-- FIXME: replace this logic stack with AJAX-->
<%#= contact_field("@obj", "contact_id",
:locals => {:options => {
:object_name => f.object_name.to_s,
:field_name => 'contact_id',
:on_display => 'display_disciplinary_notes(); display_contact_notes();'
}}
) %>
<%= f.label :closed, "Is this slot closed?" %>
<%= f.check_box :closed %>
<!--Contact Section END-->
<!--Attendance / Call Status End-->
<% if f.object.id && f.object.contact_id %>
<div class="flex-row">
<div class="col-25"><label for="assignment_attendance_type_id">Attendance:</label></div>
<div class="col-75"><%= select(f.object_name,
"attendance_type_id",
AttendanceType.all.sort_by(&:id).collect {|p| [ p.name, p.id ] },
:include_blank => true) %></div>
</div>
<div class="flex-row">
<div class="col-25"><label for="assignment_call_status_type_id">Call status:</label></div>
<div class="col-75"><%= select(f.object_name,
"call_status_type_id",
([["not called yet", ""]] + CallStatusType.all.sort_by(&:id).collect {|p| [ p.name, p.id ] }),
:include_blank => false) %></div>
</div>
<% end %>
<!-- Attendance / Call Status End-->
<!-- LOCK VERSION-->
<div class="flex-row">
<div class="col-25">
<%= f.label :lock_version %>
</div>
<div class="col-75">
<%= f.number_field :lock_version %>
</div>
</div>
<!-- LOCK end-->
</div>
</div>
</div>
<div class="modal-footer d-flex justify-content-between">
<div class="edit_icons d-flex flex-row">
<div class="d-flex flex-column">
<!-- <a href="/assignments/edit/<%#= skedj.current.id %>" title="split"><i class="fa fa-share-alt-square fa-lg" aria-hidden="true"></i> Split</a>-->
<!-- <a href="/assignments/copy/<%#= skedj.current.id %>" title="copy"><i class="fa fa-files-o fa-lg" aria-hidden="true"></i> Copy</a>-->
</div>
<div class="d-flex flex-column">
<%#= link_to '<i class="fa fa-pencil-square-o fa-lg" aria-hidden="true"></i>Edit'.html_safe, edit_assignment_path, remote: true%>
<!-- <a href="#" onclick="reassign(<%#= skedj.current.id %>); return false;" title="reassign"> <i class="fa fa-refresh fa-lg" aria-hidden="true"></i> Reassign</a>-->
</div>
</div>
<div>
<button type="button" class="btn btn-secondary mr-2" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary"><%= f.submit "Submit" %></button>
<!-- <input id="assignment_submit" name="commit" type="submit" value="Update">-->
</div>
</div>
</div>
<% end %>
_display.html.erb
<% @contact = contact %>
<div class="FONSO contact_display">
<div class="name large"><%= h @contact.display_name %></div>
<br />
<div class="id">
<%= ( @contact.contact_types.map {|c_t|
h(c_t.description)
}.sort << (@contact.is_organization ? 'organization' : 'person')
).join(', ') %>
(id: <%= @contact.id %>, created: <%= @contact.created_at.nil? ? "unknown" : @contact.created_at.to_date %>
<%#= ", login: #{h @contact.user.login}" if @contact.user %>)
</div>
<br />
<div class="address"><%= h @contact.address %><br />
<%= h @contact.city %>, <%= h @contact.state_or_province %> <%= h @contact.postal_code %>
</div>
<br />
<!--TODO: why this not show up?-->
<div class="contact_methods">
<span>CONTACT METHODS:</span><br />
<% for method in @contact.sorted_contact_methods %>
<%= h method.display %><br />
<% end %>
</div>
<br />
<% if @contact.has_areas_disciplined_from? or (@contact.notes && @contact.notes != '') %>
<div class="contact_comments">
<% if @contact.has_areas_disciplined_from? %>
Cannot volunteer in these areas (check with a staff member for assistance):<br />
<ul>
<% @contact.areas_disciplined_from.map(&:name).each do |d| %>
<li><%= d %></li>
<% end %>
</ul>
<% end %>
<% if @contact.notes && @contact.notes != '' %>
<span>Notes:</span><br/>
<%= h(@contact.notes).gsub(/\n/, "") %>
<% end %>
</div>
<% end %>
<% checked_since = @contact.spec_sheets_since_last_adoption("checker").length %>
<% built_since = @contact.spec_sheets_since_last_adoption("builder").length %>
<% if (checked_since + built_since) > 0 %>
<div>
Computers QAed since last adoption: <%= checked_since %><br/>
Computers Built since last adoption: <%= built_since %><br/>
</div>
<% end %>
<% attends = @contact.assignments.select{|x| x.attended? and x.volunteer_shift.class_credit}.map{|x| x.volunteer_shift.volunteer_event}.map{|x| x.description + " on " + x.date.strftime("%D")}.join(", ") %>
<% if !attends.blank? %>
Attended Classes:<br />
<%= attends %><br />
<% end %>
<!--ASSOCIATIONS BLOCK-->
<div class="associations">
<% if coveredness_enabled %>
<%=
"Fully Covered: " +
case @contact.fully_covered
when nil then "UNKNOWN"
when true then "Yes"
when false then "No"
end
%>
</div>
<% end %>
<br />
</div>