Rails5 what on earth is this assignment.errors showing me

Viewed 45

I have a form I'm using for submission..I've got a gnarly method "create_shift" in my controller to handle said form...but here is the catcher... have to use a preexisting database and the relations are....interesting

the form fails to submit with a "method_missing" error. Doing a assignment.errors gives me this output that I do. not. understand.

What on earth is this telling me? I have missing form fields? When I try to submit the form with "attendance_type" and "call_status_type" coded in via my "create_shift" I still get a different error which I'll list at the bottom of this post...

So first the error output I get with NO.."attendance_type" and "call_status_type" added in my "create_shift"...

enter image description here

_form.html.erb

<!--This is NEW action form-->

<%= form_for @assignment, :url => @my_url, remote: true do |f| %>

<!--  #FIXME need a fields_for 4 the volunteer_event-->

  <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 %>

          <!--VOLUNTEER SHIFT-->
          <!--TODO: make this a partial under field_for-->
          <%= f.fields_for :volunteer_event do |builder| %>
            <%= render 'assignments/volunteer_shift_fields', vs: builder %>
          <% end %>
          <!--TODO: Volunteer Shift end -->


          <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/contact_display', locals: { contact:f.object.contact} %>
            <% else %>
              <div>no contact attatched- _form.html called</div>
              <%#= 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 start-->
          <% 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 %>

Here is the Model

assignment.rb

class Assignment < ApplicationRecord
  # attr_accessor :volunteer_event ,:contact_id #why is this volunteer_event and not volunteer_shift???
  belongs_to :volunteer_shift
  has_one :volunteer_task_type, :through => :volunteer_shift, :source => :volunteer_task_type
  belongs_to :contact ,optional: true
  validates_presence_of :volunteer_shift #belongs_to takes care of this now
  validates_associated :volunteer_shift
  belongs_to :attendance_type
  belongs_to :call_status_type
  validates_presence_of :set_date, :if => :volshift_stuck #belongs_to takes care of this now??
  accepts_nested_attributes_for :volunteer_shift, allow_destroy: true

  delegate :set_date, :set_date=, :to => :volunteer_shift
  delegate :set_description, :set_description=, :to => :volunteer_shift

  has_one :contact_volunteer_task_type_count, lambda{||
    {:conditions => 'contact_volunteer_task_type_counts.contact_id = #{defined?(attributes) ? contact_id : "assignments.contact_id"}', :through => :volunteer_shift, :source => :contact_volunteer_task_type_counts}
  }
  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)}

  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

  attr_accessor :attendance_type_id


# 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
    return unless volunteer_shift
    self.volunteer_shift.volunteer_event.date.strftime("%D") + " " + self.time_range_s + " " + self.slot_type_desc
  end

  def roster_title
    return unless volunteer_shift
    self.volunteer_shift.roster.name
  end

def date
     return unless volunteer_shift
     volunteer_shift.date
   end

  #full calendar uses this method name....see the assignment.json.jbuilder
  def event_date
    return unless volunteer_shift
    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

  before_validation :set_values_if_stuck
  def set_values_if_stuck
    return unless (volshift_stuck || volunteer_shift)
    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)
    return unless volunteer_shift
    self.volunteer_shift.attributes=(attrs) # just pass it up
  end

  def volshift_stuck
    return unless volunteer_shift
    self.volunteer_shift&.stuck_to_assignment
  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

and 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
    add_shift
    # @assignment.volunteer_shift.build
    @my_url = {:action => "create", :id => params[:id]}
  end

  # GET /assignments/1/edit
  def edit
  end
  def edit_old #dumb "stuff" from older app
    if @assignment
      @assignments = [@assignment]
    else
      begin
        @assignments = params[:id].split(",").map{|x| Assignment.find(x)}
        @assignment = @assignments.first
      rescue
        flash[:error] = $!.to_s
        redirect_skedj(request.env["HTTP_REFERER"], "")
        return
      end
    end
    @referer = request.env["HTTP_REFERER"]
    @my_url ||= {:action => "update", :id => params[:id]}
    render :action => 'edit'
  end

  # POST /assignments or /assignments.json
  def create
    create_shift
    # @assignment = Assignment.new(assignment_params)
    #
    # # error wants contact.id not contact_id ???
    #
    # respond_to do |format|
    #   if @assignment.save
    #     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

  def add_shift   # FIXME: evil brought over from old app
    ve = nil
    if !params["id"].blank?
      ve = VolunteerEvent.find_by_id(params["id"])
    else
      ve = VolunteerEvent.new
    end
    vs = ve.volunteer_shifts.new
    vs.program = Program.find_by_name("intern")
    #    vs.slot_count = 1
    vs.volunteer_event_id = ve.id if ve.id
    vs.volunteer_event = ve
    a = vs.assignments.new
    a.volunteer_shift = vs
    vs.stuck_to_assignment = true
    vs.not_numbered = true
    @assignments = vs.assignments = [a]
    @referer = request.env["HTTP_REFERER"]
    @my_url = {:action => "create_shift", :id => params[:id]}
    @assignment = a
    # binding.pry
    # render :partial => 'assignments/new'
    # render :partial => 'assignments/edit' #<--original
  end

  def create_shift # FIXME: evil brought over from original code base
    # @fonso = @assignment.inspect
    ve = nil
    # Fixme: building volunteer shifts variable "vs" and associating with assignment
    if !params["id"].blank?
      ve = VolunteerEvent.find(params["id"])
    else
      if params["roster_id"].blank? || params["assignment"]["set_date"].blank?
        ve = VolunteerEvent.new # won't save
      else
        ve = Roster.find_by_id(params["roster_id"]).vol_event_for_date(params["assignment"]["set_date"])
      end
    end
    vol_shift = ve.volunteer_shifts.new
    vol_shift.stuck_to_assignment = true
    vol_shift.not_numbered = true

    #fixme: volunteer shifts variable "vol_shift" and association with assignment end
    call_status_type = CallStatusType.find_by_id(params["assignment"]["call_status_type_id"])  #fixme: this does not fix the problem
    attendance_type = AttendanceType.find_by_id(params["assignment"]["attendance_type_id"]) #fixme: this does not fix the problem

    # FIXME: vs.attributes=(params["assignment"]["volunteer_shift_attributes"]) # original needs to be rebuilt 4 this system
    h0 = {"volunteer_task_type_id" => params["volunteer_task_type_id"]}
    h1 = {"roster_id" => params["roster_id"]}
    h2 = {"program_id" => params["program_id"]}
    h3 = {"set_description" => params["set_description"]}
    #h4 = {"attendance_type" => attendance_type.name}            #fixme: this does not fix the problem
    #h5 = {"call_status_type" => call_status_type}          #fixme: this does not fix the problem
    hash_arr = [h0,h1,h2,h3]  #fixme: no h4 or h5

    volunteer_shift_attributes = hash_arr.reduce { |acc, h| (acc || {}).merge h }
    #binding.pry
    vol_shift.attributes = volunteer_shift_attributes #fixme: fracks up here but why?
    #fixme: vs.attributes fix end

    #FIXME: building variable - @assignments END
    assignment = vol_shift.assignments.new

    vol_shift = assignment.volunteer_shift

    assignment.attributes = (assignment_params) #<----magic happens here
    @assignments = [assignment]
    #fixme: building variable - @assignments END


    #FIXME: wtf is it and why is it?
    vol_shift.assignments = [assignment]
    vol_shift.set_values_if_stuck #fixme: <---- drill into this one
    binding.pry

    vs.assignments = []

    @success = assignment.valid? && vs.save #fixme: <--------what was the valid? error here?

    @assignment = assignment #fixme: <-----------------------@assignment is finally built here

    # fixme: the above lines are merging params from one into the other in the old app. to create the new volunteer_shift.

    respond_to do |format|

      if @success
        vol_shift = vol_shift.reload
          @assignment = a = vol_shift.assignments.new
          a.volunteer_shift = vol_shift
          #    a.volunteer_shift_id = vs.id
          a.attributes = (params["assignment"])
          @assignments = vol_shift.assignments = [a]

        format.html { redirect_to @assignment, notice: "Assignment was successfully created." }
        format.json { render :show, status: :created, location: @assignment }
      else
        vs.destroy
        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 -original
  #
  #   @assignment.update(assignment_params)
  # end


  def update
    unless params[:assignment]
      redirect_to :action => "index"
      return
    end
    @my_url = {:action => "update", :id => params[:id]}
    last_id = nil
    begin
      @assignments = params[:id].split(",").map{|x| last_id = x; Assignment.find(x)}
    rescue ActiveRecord::RecordNotFound
      flash[:jsalert] = "The assignment (##{last_id.to_i.inspect}) seems to have disappeared or never existed. It is possible somebody else has modified or deleted it."
      rt = params[:assignment].delete(:redirect_to)
      redirect_skedj(rt, "")
      return
    end
    lv = params["lock_versions"]
    ac = params["assigned_contacts"] || {}
    @assigned_contacts = []
    @replaced_contacts = []
    ret = true
    @assignments.each do |as|
      as.lock_version = lv[as.id.to_s]
      if as.lock_version_changed?
        as.errors.add("lock_version", "is stale for this assignment, which means it has been edited by somebody else since you opened it, please try again")
        ret = false
      end
      if as.contact_id && as.contact_id.to_s != params[:assignment][:contact_id].to_s
        @assigned_contacts << as.contact
        unless ac[as.contact_id.to_s] && ac[as.contact_id.to_s] == "replace"
          as.errors.add("contact_id", "has been changed, please confirm below that the volunteer who is already assigned to the shift should be removed")
          ret = false
        else
          @replaced_contacts << as.contact_id
        end
      end
    end
    rt = params[:assignment].delete(:redirect_to)

    js_alert = nil

    if ! ret
      @assignment = Assignment.new
      @assignment.volunteer_shift = @assignments.first.volunteer_shift
      @assignment.attributes=(params[:assignment]) # .. ? .delete("volunteer_shift_attributes")
    end

    @assignments.each{|x|
      if ret
        @assignment = x
        bc = x.contact_id
        ret = !!(x.update_attributes(params[:assignment]))
        if bc != x.contact_id and x.first_time_in_area?
          alert = "#{x.contact.display_name} (##{x.contact_id}) has never logged hours for the #{x.volunteer_shift.volunteer_task_type.description} task type. Please remind the volunteer of the requirements for this area."
          if x.volunteer_shift.volunteer_event and x.volunteer_shift.volunteer_event.notes and x.volunteer_shift.volunteer_event.notes.length > 0
            alert += "\n\nSome suggested notes saved in the database for this event are:\n" + x.volunteer_shift.volunteer_event.notes
          end
          js_alert = alert
        end
      end
    }

    if ret && @assignment.contact and not @assignment.contact.is_old_enough?
      msg = "This volunteer is not yet #{Default['minimum_volunteer_age']} years old (based on their saved birthday: #{@assignment.contact.birthday.to_s}).\nPlease remind the volunteer that they must have an adult with them to volunteer."
      if js_alert == nil
        js_alert = msg
      else
        js_alert = msg + "\n\n" + js_alert
      end
    end

    flash[:jsalert] = js_alert if js_alert

    if ret
      flash[:notice] = 'Assignment was successfully updated.'
      redirect_skedj(rt, @assignment.volunteer_shift.date_anchor)
    else
      @referer = rt
      render :action => "edit"
    end
  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
      #fixme: ,volunteer_shift_attributes: [:???, :???, :???] <--- insert this below?
            params.require(:assignment).permit(:title, :set_date, :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, :description, volunteer_shift_attributes: [:volunteer_task_type_id,:roster_id,:program_id,:set_description,:set_date,:id,:destroy])
      # params.require(:assignment).permit(:title, :set_date, :date_range, :contact_id, :start_time, :end_time, :start, :end, :attendance_type_id, :notes, :call_status_type_id, :closed, :lock_version, :color, volunteer_shift_attributes: [:volunteer_task_type_id,:roster_id,:program_id,:set_description,:set_date,:id,:destroy])
    end
end

oh and the volunteer_shift.rb model

class VolunteerShift < ApplicationRecord
  validates_presence_of :roster_id
  validates_presence_of :end_time
  validates_presence_of :start_time

  has_many  :assignments

  belongs_to :volunteer_default_shift
  belongs_to :volunteer_task_type
  belongs_to :roster
  belongs_to :volunteer_event
  belongs_to :program

  has_many :contact_volunteer_task_type_counts, :primary_key => 'volunteer_task_type_id', :foreign_key => 'volunteer_task_type_id' #:through => :volunteer_task_type


  def validate
    errors.add("end_time", "is before the start time") unless self.start_time && self.end_time && self.start_time < self.end_time
  end

  def self.week_for_date(d)
    long_time_ago = Date.new(1901, 12, 22)
    difference = (d - long_time_ago).to_int
    ((difference / 7) % 2 ) == 0 ? "A" : "B"
  end

  def weeknum
    1 + ((self.date.day - 1) / 7)
  end

  def week
    VolunteerShift.week_for_date(self.date)
  end

  def slot_number=(a)
    write_attribute(:slot_number, a)
    self.not_numbered = (!slot_number)
  end

  def set_description
    self.description
  end

  def set_description=(desc)
    self.description=(desc)
  end

  def set_date_set
    binding.pry
    @set_date_set #fixme: <----- nil here...breaking here?
  end

  def set_date=(val)
    binding.pry
    @set_date_set = true
    @set_date = val
  end

  def set_date
    @set_date_set ? @set_date : self.volunteer_event.date
  end

  def set_values_if_stuck(assn_in = nil)
    return unless self.stuck_to_assignment #<---it's a boolean in the database
    assn = assn_in || self.assignments.first
    return unless assn
    self.start_time = assn.start_time
    self.end_time = assn.end_time
    return unless self.volunteer_event_id.nil? || self.volunteer_event.description.match?(/^Roster #/)
    # return unless set_date_set #fixme:<--- pry me...is this asking if date is set??

    roster = Roster.find_by_id(self.roster_id)

    if roster and !(set_date == nil || set_date == "")
      ve = roster.vol_event_for_date(set_date)
      ve.save! if ve.id.nil?
      self.volunteer_event = ve
      self.volunteer_event_id = ve.id
    else
      if self.volunteer_event.nil?
        self.volunteer_event = VolunteerEvent.new
      end
    end

  end

  def shift_display
    time_range_s + ((!(self.description.nil? or self.description.blank?)) ? (": " + self.description) : "")
  end

  def time_range_s
    return unless self.read_attribute(:start_time) and  self.read_attribute(:end_time)
    (self.my_start_time("%I:%M") + ' - ' + self.my_end_time("%I:%M")).gsub( ':00', '' ).gsub( ' 0', ' ').gsub( ' - ', '-' ).gsub(/^0/, "")
  end

  def my_start_time(format = "%H:%M")
    read_attribute(:start_time).strftime(format)
  end

  def self._parse_time(time)
    Time.mktime(2000, 01, 01, *time.split(":").map(&:to_i))
  end

  def my_start_time=(str)
    write_attribute(:start_time, VolunteerShift._parse_time(str))
  end

  def my_end_time(format = "%H:%M")
    read_attribute(:end_time).strftime(format)
  end

  def my_end_time=(str)
    write_attribute(:end_time, VolunteerShift._parse_time(str))
  end

  def self.range_math(*ranges)
   ... #cutting this out so the question can fit this post
  end

  def fill_in_available
    return if self.stuck_to_assignment #<-- it's a boolean in the database
    Thread.current['volskedj_fillin_processing'] ||= []
    if Thread.current['volskedj_fillin_processing'].include?(self.id)
      return
    end
    begin
      Thread.current['volskedj_fillin_processing'].push(self.id)
      Assignment.where(volunteer_shift_id: self.id).select{|x| x.contact_id.nil? and !x.closed}.each{|x| x.destroy}
      inputs = [[(self.read_attribute(:start_time)), (self.read_attribute(:end_time))]]
      Assignment.where(volunteer_shift_id: self.id).select{|x| !x.cancelled?}.each{|x|
        inputs.push([(x.start_time), (x.end_time)])
      }
      results = self.class.range_math(*inputs)
      results.each{|x|
        a = Assignment.new
        a.volunteer_shift_id, a.start_time, a.end_time = self.id, x[0], x[1]
        a.volunteer_shift = self
        a.closed = self.volunteer_event.nowalkins
        a.save!
      }
    ensure
      Thread.current['volskedj_fillin_processing'].delete(self.id)
    end
  end

  after_save :fill_in_available

  def date
    self.volunteer_event.date
  end

  def date_display
    self.date.strftime('%A, %B %d, %Y').gsub( ' 0', ' ' )
  end

  def date_anchor
    self.date ? self.date.strftime('%Y%m%d') : ''
  end

  def time_shift(val)
    self.start_time += val
    self.end_time += val
  end

  def left_method_name
    [self.volunteer_task_type_id.nil? ? self.volunteer_event.description : self.volunteer_task_type.description, self.slot_number].select{|x| !x.nil?}.join(", ")
  end

  def left_unique_value
    left_method_name
  end

  def description_and_slot
    ((self.volunteer_task_type_id || -1) * 1000) + (self.not_numbered ? 0 : self.slot_number)
  end

  def weekday
    Weekday.find_by_id(self.date.strftime("%w"))
  end
end

And now here is the error output I get WITH.."attendance_type" and "call_status_type" added in my "create_shift"...

(FYI: they are added by h4 and h5 to the hash in the create_shift method)...I get this error...

 ActiveModel::UnknownAttributeError - unknown attribute 'attendance_type' for VolunteerShift.:
1 Answers
h4 = {"attendance_type" => attendance_type.name} #fixme: this does not fix the problem is the cause of your problem here.

h4 get's wrapped up into an array and then the whole array get's shoved into volunteer_shift_attributes

volunteer_shift_attributes = hash_arr.reduce { |acc, h| (acc || {}).merge h }

Which in turn get's assigned to the volunteer_shift record that does not have an attendence_type column in your database. To get past this error just comment out the line

#h4 = {"attendance_type" => attendance_type.name} #fixme: this does not fix the problem is the cause of your problem here.

This leaves you with a logic error, you presumably need to set the attendance_type value on something, probably your assignment record but get that commented out and see where that leaves you, you can worry about the assignment after you have got past this error. That's a logic problem to solve not a coding error

Related