Каков код по умолчанию для массового has_many :через назначение соединения в рельсах?

StackOverflow https://stackoverflow.com/questions/1130642

Вопрос

У меня есть базовое двунаправленное отношение has_many :through:

calendars have many calendar_calendar_events
calendars have many events through calendar_calendar_events


events have many calendar_calendar_events
events have many calendars through calendar_calendar_events

Я хочу назначить календари событию с базовыми calendar_ids= функция, которая устанавливает has_many :through, однако я хочу переопределить эту функцию, чтобы добавить немного дополнительной магии.Я просмотрел исходный код рельсов и не смог найти код этой функции.Мне интересно, может ли кто-нибудь указать мне на это.Затем я переопределю его для этого класса, чтобы добавить то, что хочу :)

Это было полезно?

Решение

Исходный код вы можете найти в файле lib/active_record/associations.rb в строке 1295

    def collection_accessor_methods(reflection, association_proxy_class, writer = true)
      collection_reader_method(reflection, association_proxy_class)

      if writer
        define_method("#{reflection.name}=") do |new_value|
          # Loads proxy class instance (defined in collection_reader_method) if not already loaded
          association = send(reflection.name)
          association.replace(new_value)
          association
        end

        define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
          ids = (new_value || []).reject { |nid| nid.blank? }
          send("#{reflection.name}=", reflection.class_name.constantize.find(ids))
        end
      end
    end

Вам определенно следует избегать перезаписи этого метода для добавления волшебных вещей.Rails иногда уже «слишком много волшебства».Я бы предложил создать виртуальный атрибут со всей вашей собственной логикой по нескольким причинам:

  1. некоторые другие методы рельсов могут полагаться на реализацию по умолчанию
  2. вы полагаетесь на определенный API, который может измениться в будущих версиях ActiveRecord.

Другие советы

После недолгих поисков я нашел это:

http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/collection_accessor_methods

Это выглядело не так, как я думал, поэтому я, вероятно, пропустил это.В итоге я переопределил метод Calendars= вместо метода Calendar_ids=, и все работает хорошо.

В ответ на ответ выше я использовал alias_method_chain, чтобы переопределить установщик по умолчанию и добавить свою функцию.Работает довольно хорошо, хотя я не уверен, почему мне нужно отправлять установщик метода вместо того, чтобы просто использовать его как обычно.Хотя, похоже, это не сработало, так что сойдет :)

  def calendars_with_primary_calendar=(new_calendars)
    new_calendars << calendar unless new_record?
    send('calendars_without_primary_calendar=', new_calendars) # Not sure why we have to call it this way
  end

  alias_method_chain :calendars=, :primary_calendar
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top