我是Ruby和Ruby on Rails的初学者,我试图在任务中运行rake命令,但当我执行以下操作时:
rake daily_tasks:process_api
rake aborted!
ActiveRecord::AssociationTypeMismatch: Estado(#47392639701120) expected, got NilClass(#47392580444120)
/home/thiagoamaralr/Desktop/proponente-master-4f8a3b2ddb02a90b2c173cf31383505018d02dd/app/services/create_programa_api.rb:21:in `call'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:7:in `block (3 levels) in <top (required)>'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:5:in `each'
/home/thiagoamaralr/Desktop/proponente-master-74f8a3b2ddb02a90b2c173cf31383505018d02dd/lib/tasks/daily_tasks.rake:5:in `block (2 levels) in <top (required)>'
Tasks: TOP => daily_tasks:process_api
(See full trace by running task with --trace)
按照我尝试运行的任务:
namespace :daily_tasks do
desc "Process the day to day tasks"
task process_api: :environment do
SiconvApi::Programa.find.each do |programa|
if programa.data_inicio_recebimento_propostas && (programa.data_inicio_recebimento_propostas.to_date >= Date.parse("2015/06/01"))
CreateProgramaApi.call(SiconvApi::Serializers::Programa.new(programa))
end
end
end
end
这是内容create_program_api.rb:
class CreateProgramaApi
def self.call(programa_api)
params = programa_api.to_h
params[:orgao] = Orgao.where("lower(name) = ?", programa_api[:orgao][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao][:nome])
params[:orgao_vinculado] = Orgao.where("lower(name) = ?", programa_api[:orgao_vinculado][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao_vinculado][:nome])
params[:orgao_executor] = Orgao.where("lower(name) = ?", programa_api[:orgao_executor][:nome].mb_chars.downcase).first_or_create(name: programa_api[:orgao_executor][:nome])
params[:estados] = []
if programa_api[:estados].size == 27
params[:estados] << Estado.find_by(sigla: 'Todos')
else
programa_api[:estados].each do |e|
params[:estados] << Estado.find_by(sigla: e)
end
end
params[:atendes] = [Atende.where("lower(name) = ?", programa_api[:atende_a].mb_chars.downcase).first_or_create(name: programa_api[:atende_a])] if programa_api[:atende_a]
params.delete(:atende_a)
programa = Programa.find_by(codigo: programa_api[:codigo])
if programa
programa.update(params)
else
Programa.create! params
end
end
end
感谢您的关注!
params[:estados]
中有nil
对象,Rails无法保存此关联。删除它们的最简单方法是在第14行之后调用params[:estados].compact!
这段代码是您的问题:
params[:estados] = []
if programa_api[:estados].size == 27
params[:estados] << Estado.find_by(sigla: 'Todos')
else
programa_api[:estados].each do |e|
params[:estados] << Estado.find_by(sigla: e)
end
end
如果没有找到记录,则#find_by
返回nil
。这就是为什么你会得到错误:
ActiveRecord::AssociationTypeMismatch: Estado(#47392639701120) expected, got NilClass
调用Programa.create!(params)
。
一种解决方案是在if
语句之后调用params[:estados].compact!
(这是使用Array#compact!
来移除任何nil
值)。
或者,你可以写这样的代码:
params[:estados] = Estadio.where(
sigla: (programa_api[:estados].size == 27 ? 'Todos' : programa_api[:estados])
)
有了这个代码,就不再需要调用compact!
了,因为如果找不到记录(即没有nil
值),我们已经得到了一个空的数组。
请注意,这里的行为并不完全相同-如果有多个Estado
记录的sigla
等于programa_api[:estados]
或'Todos'
中的一个,会发生什么?以前您只获取"第一个"这样的记录,而现在您将获取所有。这可能不是问题(甚至可能是正确的行为!!)——至少这只是需要注意的事情。