HMT collection_singular_ids = удаление моделей соединения является прямым, обратные вызовы уничтожения не запускаются - PullRequest
9 голосов
/ 17 декабря 2010

Просто столкнулся с проблемой с has_many: через ассоциацию и после / до-уничтожения обратные вызовы не запускаются.

Скажем, у меня есть пользователи, группы и промежуточное отношение, называемое членством.У меня есть форма, которая позволяет пользователям регистрироваться в группах, создавая новую запись о членстве, когда они отмечают соответствующие флажки.В основном массив group_ids.

Выглядит примерно так:

Which group would you like to join? (check all that apply)
[] Group A
[] Group B
[] Group C

И я хочу записать такие действия, как присоединение к группе или выход из группы в таблицу журнала активности, и выполнять некоторые другие действияважные thigns.

Я определил следующее:

class Group < AR::Base
  has_many :memberships
  has_many :users, :through => :memberships
end

class Membership < AR::Base
  belongs_to :user
  belongs_to :group

  after_create :log_event_to_audit_table
  after_destroy :log_event_to_audit_table

end

class User < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships

  attr_accessible :group_ids   # enables mass-assignment
end

Когда создается новая запись о членстве, after_create запускается, как и ожидалось.Тем не менее, after_destroy не запускается!

После поиска в Google и чтения документов я обнаружил причину:

"Автоматическое удаление моделей соединения является прямым, не уничтожатьобратные вызовы запускаются "- из Ruby Guides.

Хмммммм ...

Таким образом, обратные вызовы уничтожения модели соединения (в данном случае Членства) не запускаются.Ну, это депрессант.Любая причина, почему?

Итак, мой вопрос, как лучше обойти эту проблему?Должен ли я определить свой собственный метод members_ids = в модели пользователя, который напрямую вызывает members.destroy?

Открыт для любых предложений о лучших методах в таком сценарии.

Спасибо!

Ответы [ 3 ]

11 голосов
/ 23 декабря 2010

После тщательного изучения документации API выясняется, что has_many и has_and_belongs_to_many ("HABTM") имеют несколько вариантов только для этого случая:

  • before_add
  • after_add
  • before_remove
  • after_remove

class User < ActiveRecord::Base
  has_many :groups, :through => :memberships, :after_remove => :your_custom_method
end

Судя по тому, сколько ответов яполучил, это не должно быть очень хорошо документированной / используемой функцией.

Просто отмечу это здесь для себя и других, которые могут спотыкаться, как я.

0 голосов
/ 28 мая 2019

добавление dependent: :destroy ко многим отношениям фактически вызывает методы before_destroy и after_destroy в классе Membership.

class User < ActiveRecord::Base
  has_many :groups, through: :memberships, dependent: :destroy
end
0 голосов
/ 07 июня 2013

Недавно я столкнулся с той же проблемой и решил ее, расширив ассоциацию и переопределив метод удаления:

class User < ActiveRecord::Base
  has_many :memberships
  has_many :groups, :through => :memberships do
    def delete(*args)
      groups = args.flatten
      # destroy memberships in order to trigger their callbacks:
      proxy_association.owner.memberships.where(group_id: groups).destroy_all
      super
    end
  end
  ...
end
...