嵌套资源的验证在构建时失败

时间:2014-07-22 14:33:06

标签: ruby-on-rails ruby-on-rails-4

我在另一个模型控制器中构建模型的实例。所有似乎工作正常,子实例使用父ID很好地创建,但只要我在此资源中添加parent_id的验证,实例就不再有效。知道我错过了什么吗?

任务模型:

class Mission < ActiveRecord::Base
    has_many :planned_times
    validates :code,            presence: true, uniqueness: { case_sensitive: false }
    validates :days_sold, presence: true
end

PlannedTime模型:

class PlannedTime < ActiveRecord::Base
    belongs_to :mission
    validates :date,        presence: true
    validates :mission_id,  presence: true # this is the validation which causes problem
end

任务控制员:

class MissionsController < ApplicationController

  def create
    @mission = Mission.new(mission_params)
    week_nums = params[:weeks].split(/[\s]*[,;\-:\/+][\s]*/).uniq
    year = params[:year].to_i
    week_nums.each do |week_num|
      date = Date.commercial(params[:year].to_i,week_num.to_i)
      @mission.planned_times.build(date: date)
    end

    if @mission.save
      flash.now[:success] = "Mission added"
    end
  end



  private

    def mission_params
      params.require(:mission).permit(:code, :days_sold)
    end
end

1 个答案:

答案 0 :(得分:2)

因此验证关联的存在有点棘手。在您的情况下,您将mission_id验证程序放在子关联上,但rails会在保存planned_time之前在mission上运行验证,因此它会失败,因为mission_id仍然是nil。此外,通过在planned_time上进行验证,它意味着如果您从未mission.planned_items.build,则验证将无法运行,因为相关的planned_time不存在并且因此不能运行其验证。

只需对代码或验证逻辑进行最少的更改,就可以使其工作如下:

class PlannedTime < ActiveRecord::Base
  belongs_to :mission
  validates :mission_id, presence: { if: ->(p) { p.mission.nil? } }
end

此部分presence: { if: ->(p) { p.mission.nil? } }将检查是否存在mission对象(尽管还没有id),如果没有任务对象,则验证将失败。非常好,现在我们知道如果没有父planned_time个对象,我们就无法创建mission。但这并没有说明mission需要创建planned_time。如果这是你想要的,那就是解决方案。虽然我想知道你是否真的想要它,但要确保mission始终与planned_time一起创建?