【问题标题】:ActiveRecord::AssociationTypeMismatch gotNilClassActiveRecord::AssociationTypeMismatch gotNilClass
【发布时间】:2016-07-20 14:28:47
【问题描述】:

我是 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_programa_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

感谢您的关注!

【问题讨论】:

  • 错误似乎源自app/services/create_programa_api.rb。请在您的帖子中包含该文件的内容。
  • @TomLord 你好,我已经编辑了帖子并添加了文件 create_programa_api.rb 的内容谢谢

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord


【解决方案1】:

params[:estados] 中有 nil 对象,Rails 无法保存此关联。 删除它们的最简单方法是在第 14 行之后调用 params[:estados].compact!

【讨论】:

    【解决方案2】:

    这段代码是你的问题:

    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' 之一,会发生什么情况?以前您只获取“第一个”这样的记录,而现在您将获取它们中的所有。这可能不是问题(甚至可能是正确的行为!!) - 至少需要注意这一点。

    【讨论】:

      猜你喜欢
      • 2017-07-08
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多