(抱歉,如果這個問題很簡單……我已經在這個問題上呆了幾天了)
所以......我最近改變了我的模型、控制器和部分 _form.html.erb 檔案來實作一個嵌套表單......
現在我的 jbuilder 檔案需要重構,但我不喜歡提取嵌套值......
原始 index.json.jbuilder
json.array! @assignments do |assignment|
date_format = assignment.all_day_event? ? '%Y-%m-%d' : '%Y-%m-%dT%H:%M:%S'
#binding.pry
json.description assignment.description <---this used to work before I added my Nested Form
# REQUIRED
json.id assignment.id
json.title assignment.roster_title
json.start assignment.event_date.strftime('%Y-%m-%d') assignment.start_time.strftime('T%H:%M:%S')
json.end assignment.event_date.strftime('%Y-%m-%d') assignment.end_time.strftime('T%H:%M:%S')
# REQUIRED end
shift_id = assignment.volunteer_shift_id.nil? ? assignment.volunteer_task_type_id : assignment.volunteer_shift_id
json.volunteer_shift_id shift_id
# DATE
json.date assignment.event_date.strftime('%Y-%m-%d')
# TIME
json.start_time assignment.start_time.strftime('T%H:%M:%S')
json.end_time assignment.end_time.strftime('T%H:%M:%S')
json.color assignment.color unless assignment.color.blank?
# json.color assignment.skedj_style unless assignment.skedj_style.blank?
json.allDay assignment.all_day_event? ? true : false
json.update_url assignment_path(assignment, method: :patch)
json.edit_url edit_assignment_path(assignment)
end
這是我得到的錯誤...
Rendering assignments/index.json.jbuilder
Assignment Load (2.1ms) SELECT "assignments".* FROM "assignments" INNER JOIN "volunteer_shifts" ON "volunteer_shifts"."id" = "assignments"."volunteer_shift_id" INNER JOIN "volunteer_events" ON "volunteer_events"."id" = "volunteer_shifts"."volunteer_event_id" WHERE ("volunteer_events"."date" BETWEEN $1 AND $2) [["date", "2021-01-05"], ["date", "2021-01-06"]]
Rendered assignments/index.json.jbuilder (27.8ms)
Completed 500 Internal Server Error in 48ms (ActiveRecord: 6.3ms)
DEPRECATION WARNING: #original_exception is deprecated. Use #cause instead. (called from real_exception at /home/fonso/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/better_errors-0.3.2/lib/better_errors/error_page.rb:82)
NoMethodError - undefined method `volunteer_event' for nil:NilClass:
app/models/assignment.rb:46:in `description'
app/views/assignments/index.json.jbuilder:12:in `block in _app_views_assignments_index_json_jbuilder__1085023644391212852_37504860'
(gem) jbuilder-2.11.2/lib/jbuilder.rb:339:in `block (2 levels) in _map_collection'
(gem) jbuilder-2.11.2/lib/jbuilder.rb:346:in `_scope'
(gem) jbuilder-2.11.2/lib/jbuilder.rb:339:in `block in _map_collection'
(gem) activerecord-5.0.7.2/lib/active_record/relation/delegation.rb:38:in `map'
(gem) activerecord-5.0.7.2/lib/active_record/relation/delegation.rb:38:in `map'
(gem) jbuilder-2.11.2/lib/jbuilder.rb:338:in `_map_collection'
(gem) jbuilder-2.11.2/lib/jbuilder.rb:216:in `array!'
(gem) jbuilder-2.11.2/lib/jbuilder/jbuilder_template.rb:90:in `array!'
app/views/assignments/index.json.jbuilder:8:in `_app_views_assignments_index_json_jbuilder__1085023644391212852_37504860'
我的新 assignments_controller 已在“new”操作和 assignment_params 中進行了修改
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
#fixme: build goes here
@assignment.volunteer_shift.build
@my_url = {:action => "create", :id => params[:id]}
end
# GET /assignments/1/edit
def edit
end
# POST /assignments or /assignments.json
def create
@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
@assignment.update(assignment_params)
end
# DELETE /assignments/1 or /assignments/1.json
def destroy
@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,
:redirect_to, :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
下面是三個相關的模型關聯
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 #fixme: remove these validations?
validates_presence_of :end_time #fixme: remove these validations?
validates_presence_of :start_time #fixme: remove these validations?
belongs_to :volunteer_default_shift
belongs_to :volunteer_task_type
has_many :assignments
belongs_to :program
belongs_to :roster
belongs_to :volunteer_event
has_many :contact_volunteer_task_type_counts, :primary_key => 'volunteer_task_type_id', :foreign_key => 'volunteer_task_type_id' #:through => :volunteer_task_type
...
end
class Assignment < ApplicationRecord
attr_accessor :volunteer_shift #,:contact_id ???
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
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 <----THIS IS BAD
accepts_nested_attributes_for :volunteer_shift, allow_destroy: true
#fixme: Nodule::DelegationError -
# This error appears when trying to show the "Add New Assignment" model on the /assignments view
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
#fixme: fix all red dots on this page
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
# 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
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
#fixme: date / set_date is fracked since old code was ported over
def date
volunteer_shift.date
end
#full calendar uses this method name....see the assignment.json.jbuilder
def event_date
self.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
# arieljuod thinks this is suspect. "belongs_to :contact" should have taken care of setting contact object
# 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
#fixme: where is stuck_to_assignment ??? WTF?
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
#for fullcalendar
def all_day_event?
self.start_time == self.start_time.midnight && self.end_time == self.end_time.midnight ? true : false
end
end
...
end
我不知道發生了什么……為什么 jbuilder 現在壞了?是因為嵌套表單嗎?它與我的模型有關系嗎?我的 assignment_params 有什么問題???
如何重寫我的 index.json.jbuilder?
(Note: I suspect I have to do some nested array stuff in my json file, but I've not done that before...https://stackoverflow.com/questions/35749301/get-nested-arrays-in-json)
UPDATE:
So, I tested a theory out If I switch branches to an earlier version pre-nested form....all my json output gets displayed. If I switch back to the nested form branch I do not get any json output that my main page uses to display. (note: I have not been able to add a new record as the link to add a new record is on the main page...that now does not get displayed). Process of elimination points to the model associations recently added when I was trying to create a Nested Form. But if I comment those lines out... line 2 and 12... in my assignment model...
class Assignment < ApplicationRecord
# attr_accessor :volunteer_shift #,:contact_id ??? <----TURN THIS OFF AND JSON DISPLAYS AGAIN
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??
#accepts_nested_attributes_for :volunteer_event, allow_destroy: true <----TURN THIS OFF
The json outputs to the main screen again no problems.
UPDATE 2:
如果我只是注釋掉 assignment.rb 的第 2 行所有 json 資料收割者
uj5u.com熱心網友回復:
錯誤資訊
NoMethodError - undefined method `volunteer_event` for nil:NilClass: app/models/assignment.rb:50:in `description'
告訴在檔案description行中的方法中50,在一個實體上app/models/assignment.rb呼叫volunteer_eventnil:NilClass
def description
self.volunteer_shift.volunteer_event.date.strftime("%D") " " self.time_range_s " " self.slot_type_desc
end
這意味著self.volunteer_shift必須回傳nil并且您的資料庫中有沒有volunteer_shift分配的分配。
此修復程式取決于您的應用程式,但一個簡單的解決方案可能是有description回傳nil時,有沒有volunteer_shift-這樣的
def description
return unless volunteer_shift
self.volunteer_shift.volunteer_event.date.strftime("%D") " " self.time_range_s " " self.slot_type_desc
end
uj5u.com熱心網友回復:
@spickermann 在他們的回答中幾乎已經解決了您的問題,但這不是一個完整的解決方案。
- 您的資料被弄亂了,因為您正在創建沒有關聯志愿者班次記錄的分配記錄。
允許發生這種情況是因為之前阻止這種情況發生的檢查已經過時,并且只能在具有這些validates_presence_of方法的舊版本 rails 中按預期作業,因此它們需要更新。
您需要進行測驗以確保這種情況不再發生,如果再次發生,您將立即收到通知。rspec、capybara 和 factorybot with guard 是我選擇的替代標準 Rails 測驗框架的工具,但是,你使用的工具應該是你的偏好,只要確保你有創建和更新分配記錄的測驗覆寫范圍,以確保你有一個有效的志愿者輪班記錄,這樣您就可以知道何時解決了導致此問題的原始問題,而不僅僅是何時處理了此特定問題。
最后,您要么需要修復您的資料,要么需要按照@spickermann 的建議,在您的分配模型中通過檢查志愿者的移位是否不為零,向在您的分配模型中使用志愿者移位的任何方法添加檢查,并且可能同時執行這兩件事。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/352023.html
