Как вы гарантируете, что has_many всегда "имеет минимум"? - PullRequest
1 голос
/ 16 января 2012

Допустим, я пишу код для моделирования автобусной станции.

Каждый fleet шин всегда имеет хотя бы один bus.Я хочу выяснить лучший способ применения этого минимального числа в модели.Последний автобус во флоте никогда не может быть уничтожен, если сам флот не будет уничтожен.

Один из подходов - захватить отношения на объекте bus.

class Bus
  ...
  before_destroy :check_minimum_busses_on_parent
end

Однако это широко игнорирует принцип единоличной ответственности.Автобус занимается проблемами флота, которые не являются его проблемой.

Я мог бы вместо этого создать bus_observer с помощью метода before_destroy.Все теперь снова с единственной ответственностью, такое чувство, что у нас больше гремит объектов, чем необходимо.

class BusObserver < ActiveRecord::Observer
  def before_destroy bus
    false if bus.fleet.busses.count <= 1
  end
end

Это, безусловно, сработает, но я не на 100% рад отделению от класса Fleet, к которому он действительно принадлежит.

Все еще допускаюфлот, чтобы уничтожить свой последний автобус

Для того, чтобы учесть возможность того, что родительский объект fleet сам может быть уничтожен, и хотят избавиться от своего последнего автобуса, я также в конечном итоге нуждаюсь в некотором кресте-связи, чтобы автобус мог выяснить, получает ли флот тоже отбивную:

class BusObserver < ActiveRecord::Observer
  def before_destroy bus
    if  bus.fleet.busses.count <= 1 
      false unless bus.fleet.currently_being_destroyed?
    end
  end
end

Это явно входит в царство чистого безобразия.Можно обернуть это в метод .bus_can_be_destroyed?, который находится на объекте флота, но это не намного лучше.

Какой самый чистый способ получить то, что я ищу?

Ответы [ 2 ]

1 голос
/ 16 января 2012

Будет ли работать с обратными вызовами ассоциации ? Вы можете использовать обратный вызов before_remove и остановить удаление, согласно документам.

1 голос
/ 16 января 2012

Не могли бы вы иметь класс Decommissioner, который, учитывая шину, соответствующим образом обрабатывает бизнес-логику?Это кажется ясным и разумным.

Это может быть даже модель ActiveRecord, если вы заинтересованы в регистрации события вывода из эксплуатации.

Что-то вроде:

class BusDecommissioner
  def initialize(bus)
    @bus = bus
  end
  def decommissionable?
    @bus.fleet.buses.size > 1
  end
  def decommission!
    @bus.destroy if decommissionable?
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...