mardi 2 novembre 2021

Rails5 method is not getting called from create action

So I have an old app I'm updating to Rails 5.0.7 (reasons)

I've ported over the original code bases "create" method but this line is giving me grief...

def create
...
    vs.attributes=(params["assignment"]["volunteer_shift_attributes"]) <--- WHY HE NOT CALLED ???
...
end

Note that ["assignment"]["volunteer_shift_attributes"]?

Well in the old code base the assignment model has this method (which I also ported over to the Rails 5 app)...

  def volunteer_shift_attributes=(attrs)
    self.volunteer_shift.attributes=(attrs) 
  end

So I'm guessing this is where is "supposed" to be getting called in the old app... ...but in the new Rails 5 app's assignment model it is not getting called. And I do not know why.

Here is the entire create action...


  def create # FIXME: evil brought over from original code base
    ve = nil
    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
    vs = ve.volunteer_shifts.new
    #    vs.slot_count = 1
    #    vs.volunteer_event_id = ve.id
    #    vs.volunteer_event = ve
    vs.stuck_to_assignment = vs.not_numbered = true
    vs.attributes=(params["assignment"]["volunteer_shift_attributes"]) <--- WHY HE NOT CALLED ???
    a = vs.assignments.new
    a.volunteer_shift = vs
    #    a.volunteer_shift_id = vs.id
    a.attributes = (params["assignment"])
    @assignments = vs.assignments = [a]
    vs.set_values_if_stuck
    vs.assignments = []
    @success = a.valid? && vs.save
    rt = params[:assignment].delete(:redirect_to)
    @my_url = {:action => "create_shift", :id => params[:id]}
    @assignment = a
    if @success
      vs = vs.reload
      @assignment = a = vs.assignments.new
      a.volunteer_shift = vs
      #    a.volunteer_shift_id = vs.id
      a.attributes = (params["assignment"])
      @assignments = vs.assignments = [a]

      if !@success
        vs.destroy
      end
    end
    if @success # and @assignment.volunteer_shift.save
      redirect_skedj(rt, ve.date_anchor)
    else
      # render :partial => 'assignments/new'
      render :partial => 'assignments/edit' #<--original
    end
  end


Here is the entire assignment model, the offending method is around line 117 (a lot of original code I've refactored for Rails 5...apologies for it's length, it is inherited code..adding here in case it is helpful)...

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

  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



  
  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


  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

  def date
    self.volunteer_shift.date
  end

  def event_date
    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


  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


  def all_day_event?
    self.start_time == self.start_time.midnight && self.end_time == self.end_time.midnight ? true : false
  end
end

What am I missing? Why is volunteer_shift_attributes nil when called inside the create action? Why is...

  def volunteer_shift_attributes=(attrs)
    self.volunteer_shift.attributes=(attrs) 
  end

...not getting called?

Thank you for your time.

Aucun commentaire:

Enregistrer un commentaire