Рельсы 4: счетчик кэша в Имеет много:через ассоциацию с зависимым:: уничтожить


Хотя подобные вопросы уже задавались:

Ни один из них на самом деле не затрагивает мою проблему.

У меня есть три модели, с has_many: через ассоциацию:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

Модель администрирования join имеет следующее атрибуты:

id
user_id
calendar_id
role
Я хотел бы подсчитать, сколько calendars у каждого user и сколько users у каждого calendar.

Я собирался использовать counter_cache следующим образом:

class Administration < ActiveRecord::Base
  belongs_to :user, counter_cache: :count_of_calendars
  belongs_to :calendar, counter_cache: :count_of_users
end

(и, конечно, соответствующие миграции для добавления :count_of_calendars в таблицу users и :count_of_users в таблицу calendars.)

Но затем я наткнулся на это предупреждение в направляющих рельсов :

4.1.2.4: зависимый

Если установить параметр: dependent в:

  • :destroy, когда объект будет уничтожен, destroy будет вызван на связанные с ним объекты.
  • :удалить, когда объект будет уничтожен, все связанные с ним объекты будут удалены непосредственно из базы данных без вызова их метод уничтожения.

Вы не должны указывать этот параметр в ассоциации belongs_to, которая является связан с Ассоциацией has_many на другом классе. Это может привести к осиротевшим записям в вашем база данных.

Таким образом, что было бы хорошей практикой подсчитать, сколько calendars имеет каждый user и сколько users имеет каждый calendar?
1 3

1 ответ:

Ну, dependent: :destroy уничтожит связанные записи, но не обновит counter_cache, так что у вас может быть неправильный счет в counter_cache. Вместо этого вы можете реализовать обратный вызов, который уничтожит связанные записи и обновит ваш counter_cache.

class Calendar < ActiveRecord::Base

  has_many :administrations
  has_many :users, through: :administrations


  before_destroy :delete_dependents

  private
  def delete_dependents
    user_ids = self.user_ids
    User.delete_all(:calendar_id => self.id)
    user_ids.each do |u_id|
      Calendar.reset_counters u_id, :users
    end
  end
end

И аналогично реализуем это для User модели тоже