Каков код по умолчанию для массового has_many: через присвоение соединения в rails? - PullRequest
1 голос
/ 15 июля 2009

У меня есть основное has_many: через двусторонние отношения:

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, однако я хочу переопределить эту функцию, чтобы добавить дополнительную магию. Я посмотрел источник rails и не могу найти код для этой функции. Мне интересно, если кто-то может указать мне на это. Затем я переопределю это для этого класса, чтобы добавить материал, который я хочу:)

Ответы [ 3 ]

2 голосов
/ 15 июля 2009

Вы можете найти исходный код в файле 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. некоторые другие методы rails могут полагаться на реализацию по умолчанию
  2. вы полагаетесь на определенный API, который может измениться в будущих версиях ActiveRecord
2 голосов
/ 15 июля 2009

После небольшой охоты я нашел это:

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

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

0 голосов
/ 16 июля 2009

В ответ на ответ выше я использовал 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
...