Rails 5 验证失败:志愿者默认事件必须存在....但是为啥会这样以及如何做到这一点
Posted
技术标签:
【中文标题】Rails 5 验证失败:志愿者默认事件必须存在....但是为啥会这样以及如何做到这一点【英文标题】:Rails 5 Validation failed: Volunteer default event must exist....but why this and how to make it soRails 5 验证失败:志愿者默认事件必须存在....但是为什么会这样以及如何做到这一点 【发布时间】:2021-12-25 01:32:54 【问题描述】:我正在将一个旧应用重新构建到 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" = $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
模型关联
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
感谢您的宝贵时间
【问题讨论】:
【参考方案1】:在你的VolunteerEvent
中有这条线
belongs_to :volunteer_default_event
自从 Ruby on 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 验证失败:志愿者默认事件必须存在....但是为啥会这样以及如何做到这一点的主要内容,如果未能解决你的问题,请参考以下文章
Rails 中的 Authorize.net - 由于身份验证值无效,用户身份验证失败
Rails 5 和设计:如何在不更改默认策略的情况下禁用基于令牌的策略上的会话
“父必须存在”和“没有为CommentsController找到模板#create,呈现head:no_content”Rails 5