I'm rebuilding an old app into Rails 5.
So I'm getting an error and I do not know why. I'm not entirely sure what it is asking for. Is this asking for a model association to be modified? I've included my model associations below, please let me know if I need to include anything else to help decipher this error.
binding.pry
vs.set_values_if_stuck
vs.assignments = []
@success = a.valid? && vs.save
# [1] pry(#<VolunteerEventsController>)> vs.set_values_if_stuck
# Roster Load (0.3ms) SELECT "rosters".* FROM "rosters" WHERE "rosters"."id" = $1 LIMIT $2 [["id", 7], ["LIMIT", 1]]
# VolunteerEvent Load (0.3ms) SELECT "volunteer_events".* FROM "volunteer_events" WHERE "volunteer_events"."description" = $1 AND "volunteer_events"."date" = $2 LIMIT $3 [["description", "Roster #7"], ["date", "2021-01-11"], ["LIMIT", 1]]
# (0.1ms) BEGIN
# (0.1ms) ROLLBACK
# (0.1ms) BEGIN
# (0.1ms) ROLLBACK
# ActiveRecord::RecordInvalid: Validation failed: Volunteer default event must exist
Model associations
class Assignment < ApplicationRecord
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??
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)}
...
end
class Roster < ApplicationRecord
has_and_belongs_to_many :skeds
belongs_to :contact_type
scope :enabled, -> {where(['enabled = ?', true])}
has_many :volunteer_shifts
has_many :volunteer_default_shifts
belongs_to :restrict_from_sked, :class_name => "Sked"
def sandbox?
name.downcase == 'sandbox'
end
def Roster.auto_generate_all
fails = []
if Roster.are_auto_generated?
Roster.enabled.reject(&:sandbox?).each do |r|
start_d = r.generated_to_date 1
end_d = Date.today eval(Default["autogenerate_volskedj_out"])
fails = fails r.auto_generate(start_d, end_d) if start_d <= end_d
end
end
return fails
end
def generated_to?(d)
generated_to_date >= d
end
def to_s
name
end
def generated_to_date
newc = Conditions.new
newc.apply_conditions({})
newc.roster_enabled = true
newc.roster_id = self.id
newc.generated_shift_enabled = true
d1 = VolunteerEvent.maximum(:date, :conditions => newc.conditions(Assignment), :joins => 'INNER JOIN "volunteer_shifts" ON volunteer_shifts.volunteer_event_id = volunteer_events.id INNER JOIN "assignments" ON assignments.volunteer_shift_id = volunteer_shifts.id LEFT OUTER JOIN "attendance_types" ON "attendance_types".id = "assignments".attendance_type_id')
d2 = VolunteerEvent.maximum(:date, :conditions => newc.conditions(ResourcesVolunteerEvent), :joins => 'INNER JOIN "resources_volunteer_events" ON resources_volunteer_events.volunteer_event_id = volunteer_events.id')
return [d1, d2, Date.today].select{|x| !!x}.max
end
def auto_generate(from, to)
results = []
begin
c = Conditions.new
c.apply_conditions({})
c.roster_enabled = true
c.roster_id = self.id
conflicts = VolunteerDefaultShift.find_conflicting_assignments(from, to, c)
skippers = conflicts.map{|x| x[1].id}
results = conflicts.map{|x| "On #{x[0]}, #{x[1].contact.display_name} (##{x[1].contact_id}) was not successfully scheduled for #{x[1].slot_type_desc} (#{self.name} roster) as they have the following conflicting shifts: #{x[2].map{|x| x.description}.join(" ")}"}
VolunteerDefaultShift.generate(from, to, c, skippers)
ResourcesVolunteerDefaultEvent.generate(from, to, c)
rescue => e
puts "ERROR: Failed to generate #{self.name} roster from #{from} to #{to}!"
puts "Please check for consistency,"
puts " error message: #{e.to_s}"
end
results
end
def Roster.are_auto_generated?
! Default["autogenerate_volskedj_out"].nil?
end
def skeds_s
self.skeds.map(&:name).sort.join(", ")
end
# note: #Keep this here so know where to find the deprecation info - Fonso
# THIS is where date value from add new record form gets inserted into a new record
def vol_event_for_date(date)
binding.pry
# VolunteerEvent.find_or_create_by_description_and_date("Roster ##{self.id}", date) <-- original
# https://guides.rubyonrails.org/4_0_release_notes.html#active-record-deprecations
VolunteerEvent.find_or_create_by(description: "Roster ##{self.id}", date: date)
binding.pry
end
def vol_event_for_weekday(wday)
# VolunteerDefaultEvent.find_or_create_by_description_and_weekday_id("Roster ##{self.id}", wday) <-- original
# https://guides.rubyonrails.org/4_0_release_notes.html#active-record-deprecations
VolunteerDefaultEvent.find_or_create_by(description: "Roster ##{self.id}", weekday_id: wday)
end
end
class VolunteerEvent < ApplicationRecord
belongs_to :volunteer_default_event
validates_presence_of :date
has_many :volunteer_shifts, :dependent => :destroy
has_many :resources_volunteer_events, :dependent => :destroy
validates_associated :volunteer_shifts
...
end
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
...
end
Thank you for your time
CodePudding user response:
In your VolunteerEvent
you have this line
belongs_to :volunteer_default_event
Since Ruby on Rails 5.0 the default for belongs_to
associations is that they must exist for the record to be valid (see article about this behavior). That basically means that each time you define an association like belongs_to :foo
there is automatically a validates_presence_of :foo
added.
You have to way to solve the issue:
You make sure that you set
volunteer_default_event
to a valid event. Oryou mark the association as optional which means is it okay when there s no
volunteer_default_event
. That can be done like this:belongs_to :volunteer_default_event, optional: true