Динамически создавать колбэки after_add и after_remove для has_many или habtm? - PullRequest
7 голосов
/ 24 января 2012

Есть ли способ динамически добавлять обратные вызовы after_add и after_remove к существующим отношениям has_many или has_and_belongs_to_many?

Например, предположим, у меня есть модели User, Thingи модель соединения UserThingRelationship, а модель User выглядит примерно так:

class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships
end

Я хотел бы иметь возможность в модуле, который расширяет User, добавить :after_add и :after_remove обратные вызовы отношения User.has_many(:things, ...).Т.е., есть что-то вроде

module DoesAwesomeStuff
  def does_awesome_stuff relationship, callback
    # or however this can be achieved...
    after_add(relationship) callback
    after_remove(relationship) callback
  end
end

, чтобы

class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships

  does_awesome_stuff :things, :my_callback
  def my_callback; puts "awesome"; end
end

было фактически таким же, как

class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships, :after_add => :my_callback, :after_remove => :my_callback

  def my_callback; puts "awesome"; end
end

Это можно сделать довольно эффективно для добавления after_saveи т. д. обратные вызовы расширяемой модели, поскольку ActiveRecord::Base#after_save - это просто метод класса.

Ответы [ 2 ]

12 голосов
/ 12 июня 2012

Самый простой будет

User.after_add_for_things << lambda do |user, thing| 
  Rails.logger.info "#{thing} added to #{user}"
end
7 голосов
/ 24 января 2012

Я смог придумать следующее с помощью ActiveRecord :: Reflection :

module AfterAdd
  def after_add rel, callback
    a = reflect_on_association(rel)
    send(a.macro, rel, a.options.merge(:after_add => callback))
  end
end

class User < ActiveRecord::Base
  extend AfterAdd

  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships

  after_add :things, :my_callback

  def my_callback
    puts "Hello"
  end
end

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

...