确保模型与同一父级关联

时间:2019-01-17 10:42:30

标签: ruby-on-rails ruby

假设我有3个相互关联的模型:

class Farm < ApplicationRecord
  has_many :horses
  has_many :events
end

class Horse < ApplicationRecord
  belongs_to :farm
  has_many :events_horses, class_name: 'Event::EventsHorse'
  has_many :events, through: :events_horses, source: :event, dependent: :destroy
end

class Event
  belongs_to :farm
  has_many :events_horses, class_name: 'Event::EventsHorse'
  has_many :horses, through: :events_horses, source: :horse, dependent: :destroy
end

class Event::EventsHorse < ApplicationRecord
  self.table_name = "events_horses"

  belongs_to :horse
  belongs_to :event

  audited associated_with: :event, except: [:id, :event_id]
end

如何确保每匹马都属于同一农场?可能的解决方案是使用自定义验证,但我想知道是否还有其他方法。我还没有其他类似Horse的模型,因此它迫使我对每个模型进行自定义验证方法。

class Event
  ...
  validate :horses_belongs_to_farm

  private

  def horses_belongs_to_farm
    horses.all? {|h| h.farm_id == farm_id}
  end   
end

1 个答案:

答案 0 :(得分:2)

我认为您使用的模型在需要一致性检查的表之间设置了过多的ID。

如果您以此方式设置模型,则无需验证马场和事件是否一致,因为数据可以确保这一点:

class Farm < ApplicationRecord
  has_many :horses
  has_many :events
end

class Horse < ApplicationRecord
  belongs_to :farm
  has_many :events, through: :farm
end

class Event < ApplicationRecord
  belongs_to :farm
  has_many :horses, through: :farm
end

如果您需要有效地访问事件中的马或事件中的马,则可以使用联接。这提供了一些简单性,清晰度和一致性。

您还应该看看Choosing Between has_many_through and has_and_belongs_to_many


[根据更新后的问题和评论进行编辑] 现在,您的模型和问题更加清楚了,我的直觉是将验证置于Event模型中会导致多余的验证。由于您的目的是确保在给定的情况下,马匹和农场保持一致,因此我将验证放在EventsHorses中:

class Event::EventsHorse < ApplicationRecord
  ...
  validate :horse_belongs_to_farm

  private

  def horse_belongs_to_farm
    horse.farm_id == event.farm_id 
  end   
end

顺便说一句,您是否拥有Event::EventsHorse而不是简单地拥有EventsHorse的单独模型?