使用has_many关联保存模型无法通过验证

时间:2019-01-10 14:40:15

标签: ruby-on-rails ruby-on-rails-5

我正在尝试将对象保存到数据库并创建has_many关联,但是验证失败。我目前正在使用Postgres在Rails 5.2上。

item.rb

class Item < ApplicationRecord
  has_many :routings,     dependent: :destroy
  has_many :work_centers, through: :routings
  validates :number, presence: true, 
                     length: { maximum: 255 },
                     uniqueness: true
  ...
end

routing.rb

class Routing < ApplicationRecord
  belongs_to :item
  belongs_to :work_center
  validates :item_id, presence: true
  validates :work_center_id, presence: true
  ...
end

work_center.rb

class WorkCenter < ApplicationRecord
  has_many :routings, dependent: :destroy
  has_many :items,    through: :routings
  validates :name, presence: true, length: { maximum: 255 }, 
                   uniqueness: { case_sensitive: false }
  validates :sequence, presence: true,
                       uniqueness: true
end

items_controller.rb

def create
  @item = Item.new(item_params)
  if @item.save
    ...
  end
end

private
  def item_params
    params.require(:item).permit(:job_id, :number, :product_type, work_center_ids: [])
  end

当我尝试在Rails控制台中创建新的Item时,它会失败并显示验证错误:

>   Item.create!(job_id: 58, number: "6872-ryan1", work_center_ids: [3,4])
ActiveRecord::RecordInvalid: Validation failed: Routings is invalid

但是,如果我先创建Item然后添加Routings,它将成功:

>   i = Item.create!(job_id: 58, number: "6872-ryan1")
 => #<Item id: 583, number: "6872-ryan1", product_type: nil, job_id: 58, created_at: "2019-01-10 14:28:16", updated_at: "2019-01-10 14:28:16">
>   i.work_center_ids = [3,4]
 => [3, 4]

我尝试将inverse_of:添加到模型:

更新后的item.rb

class Item < ApplicationRecord
  has_many :routings,     dependent: :destroy
  has_many :work_centers, through: :routings, inverse_of: :item
  ...
end

更新了work_center.rb

class WorkCenter < ApplicationRecord
  has_many :routings, dependent: :destroy
  has_many :items,    through: :routings, inverse_of: :work_center
end

但是现在我得到了另一个错误:

> Item.create!(job_id: 58, number: "6872-ryan2", work_center_ids: [3])
ActiveRecord::InverseOfAssociationNotFoundError: Could not find the inverse association for work_centers (:item in WorkCenter)

已编辑以显示模型中的验证

1 个答案:

答案 0 :(得分:1)

从ROR的第5版开始,belongs_to关联默认情况下经过验证,因此在路由模型中不需要这些行:

validates :item_id, presence: true
validates :work_center_id, presence: true

如果删除后您可以在没有item_id或work_center_id的情况下创建路由,请在配置文件中将belongs_to_required_by_default = false更改为true

无论如何,您应该验证关联模型的存在,而不是其ID。在前一种情况下,您检查数据库中是否存在具有给定id的项目(例如),在后一种情况下,您仅检查item_id列是否具有某些值。