Rails 5 验证失败:志愿者默认事件必须存在....但为什么会这样以及如何做到这一点
Rails 5 Validation failed: Volunteer default event must exist....but why this and how to make it so
我正在将旧应用重建为 Rails 5.
所以我收到一个错误,我不知道为什么。我不完全确定它在要求什么。这是要求修改模型关联吗?我在下面包含了我的模型关联,如果我需要包含任何其他内容来帮助破译此错误,请告诉我。
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" = LIMIT [["id", 7], ["LIMIT", 1]]
# VolunteerEvent Load (0.3ms) SELECT "volunteer_events".* FROM "volunteer_events" WHERE "volunteer_events"."description" = AND "volunteer_events"."date" = LIMIT [["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
模特协会
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
感谢您的宝贵时间
在你的VolunteerEvent
中你有这条线
belongs_to :volunteer_default_event
自 Ruby 在 Rails 5.0 以来,belongs_to
关联的默认设置是它们必须存在才能使记录有效(参见 article about this behavior)。这基本上意味着每次你定义一个像 belongs_to :foo
这样的关联时,都会自动添加一个 validates_presence_of :foo
。
您有解决问题的方法:
您确保将 volunteer_default_event
设置为有效事件。或者
您将关联标记为可选,这意味着当没有 volunteer_default_event
时可以吗?可以这样做:
belongs_to :volunteer_default_event, optional: true
我正在将旧应用重建为 Rails 5.
所以我收到一个错误,我不知道为什么。我不完全确定它在要求什么。这是要求修改模型关联吗?我在下面包含了我的模型关联,如果我需要包含任何其他内容来帮助破译此错误,请告诉我。
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" = LIMIT [["id", 7], ["LIMIT", 1]]
# VolunteerEvent Load (0.3ms) SELECT "volunteer_events".* FROM "volunteer_events" WHERE "volunteer_events"."description" = AND "volunteer_events"."date" = LIMIT [["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
模特协会
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
感谢您的宝贵时间
在你的VolunteerEvent
中你有这条线
belongs_to :volunteer_default_event
自 Ruby 在 Rails 5.0 以来,belongs_to
关联的默认设置是它们必须存在才能使记录有效(参见 article about this behavior)。这基本上意味着每次你定义一个像 belongs_to :foo
这样的关联时,都会自动添加一个 validates_presence_of :foo
。
您有解决问题的方法:
您确保将
volunteer_default_event
设置为有效事件。或者您将关联标记为可选,这意味着当没有
volunteer_default_event
时可以吗?可以这样做:belongs_to :volunteer_default_event, optional: true