Not understanding why my record is not being updated. Where do I look? How do I debug?
Here is the rollback message I see...
66: def update #this is NOT working...use imported older version below
=> 67: binding.pry
68:
69: @assignment.update(assignment_params)
70: end
[1] pry(#<AssignmentsController>)> @assignment.update(assignment_params)
(0.2ms) BEGIN
VolunteerShift Load (0.2ms) SELECT "volunteer_shifts".* FROM "volunteer_shifts" WHERE "volunteer_shifts"."id" = $1 LIMIT $2 [["id", 545496], ["LIMIT", 1]]
Contact Load (0.3ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = $1 LIMIT $2 [["id", 137424], ["LIMIT", 1]]
VolunteerTaskType Load (0.3ms) SELECT "volunteer_task_types".* FROM "volunteer_task_types" WHERE "volunteer_task_types"."id" = $1 LIMIT $2 [["id", 41], ["LIMIT", 1]]
Roster Load (0.2ms) SELECT "rosters".* FROM "rosters" WHERE "rosters"."id" = $1 LIMIT $2 [["id", 7], ["LIMIT", 1]]
VolunteerEvent Load (0.2ms) SELECT "volunteer_events".* FROM "volunteer_events" WHERE "volunteer_events"."id" = $1 LIMIT $2 [["id", 52679], ["LIMIT", 1]]
(0.2ms) ROLLBACK
=> false
[2] pry(#<AssignmentsController>)> exit
Here is the model...
class Assignment < ApplicationRecord
# attr_accessor :volunteer_event ,:contact_id #why is this here???
# attr_accessor :redirect_to
belongs_to :volunteer_shift, optional: true
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)}
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 contact_id=(newval)
self.write_attribute(:contact_id, newval)
self.contact = Contact.find_by_id(newval.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
# 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 first_time_in_area?
if self.contact and self.volunteer_shift and self.volunteer_shift.volunteer_task_type
return !ContactVolunteerTaskTypeCount.has_volunteered?(self.contact_id, self.volunteer_shift.volunteer_task_type_id)
else
return false
end # and self.contact_id_changed? moved outside because we use update_attributes
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 }
scope :for_contact, lambda{|assignment|
tcid = assignment.contact.id
{ :conditions => ['contact_id = ?', tcid] }
}
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
Here is the entire 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
end
# GET /assignments/1/edit <-- ORIGINAL
# def edit
# end
def edit #dumb "stuff" from older app
logger.debug "assignments_controller EDIT called"
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
# PATCH/PUT /assignments/1 or /assignments/1.json
def update #this is NOT working...use imported older version below
binding.pry
@assignment.update(assignment_params)
end
def update_from_old_code #from original garbage code
logger.debug "assignments_controller UPDATE called"
unless params[:assignment]
redirect_to :action => "index"
return
end
@my_url = {:action => "update", :id => params[:id]}
last_id = nil
begin
# is @assignments broken here??
@assignments = params[:id].split(",").map{|x| last_id = x; Assignment.find(x)}
# binding.pry
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
# binding.pry
lv = params["lock_versions"]
ac = params["assigned_contacts"] || {}
@assigned_contacts = []
@replaced_contacts = []
ret = true #WTF why???
#500 error caused by ??
@assignments.each do |as|
as.lock_version = lv[as.id.to_s]
# binding.pry
if as.lock_version_changed?
binding.pry
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
binding.pry
@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
# binding.pry
if ! ret
@assignment = Assignment.new
@assignment.volunteer_shift = @assignments.first.volunteer_shift
@assignment.attributes=(params[:assignment]) # .. ? .delete("volunteer_shift_attributes")
end
# binding.pry
@assignments.each{|x|
# binding.pry
if ret #what does ret mean???
@assignment = x
bc = x.contact_id
binding.pry
ret = !!(x.update(params[:assignment])) #TODO not working...what is "!!" here? THIS IS THE BREAKING LINE
binding.pry
# how to say if updated then true ??
if ret
binding.pry
flash[:notice] = 'Assignment was successfully updated.'
else
binding.pry
render :action => "edit"
end
# when are the values x updated?
end
}
end
# DELETE /assignments/1 or /assignments/1.json
def destroy #this is working
@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
Any help is appreciated
Thank you for your time.
CodePudding user response:
You can try update!, which should show the exact cause of rollback.
@assignment.update!(assignment_params)
CodePudding user response:
change your code in update method with ! like below so it will help you to find error with exact reason with exception
@assignment.update!(assignment_params)