Domanda

Ho un has_many base: attraverso la relazione che è bidirezionale:

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

Sono voler assegnare i calendari ad un evento con la funzione di base che calendar_ids= has_many: attraverso il set up, però, voglio ignorare questa funzione per aggiungere un po 'di magia in più. Ho avuto uno sguardo attraverso la sorgente di rotaie e non riesco a trovare il codice per questa funzione. Mi chiedo se qualcuno mi potrebbe puntare ad esso. Io poi sovrascrivere per questa classe di aggiungere le cose che voglio:)

È stato utile?

Soluzione

È possibile trovare il codice sorgente nel file lib/active_record/associations.rb alla riga 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

Si dovrebbe evitare di sovrascrivere quali questo metodo per aggiungere roba magia. Rails è già "troppo magico" a volte. Vorrei suggerire di creare un attributo virtuale con tutta la tua logica personalizzata per diversi motivi:

    metodi
  1. alcune altre rotaie potrebbero contare sulla implementazione di default
  2. si basano su una specifica API che potrebbe andare a cambiare in futuro versioni ActiveRecord

Altri suggerimenti

Dopo un po 'di caccia ho trovato:

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

Non sembrava come quello che ho pensato che sarebbe simile, ecco perché probabilmente ho perso. Ho finito per l'override del metodo di calendari = invece del calendar_ids = metodo e tutto funziona bene.

In risposta alla risposta di cui sopra, ho usato alias_method_chain per ignorare il setter di default e aggiungere la mia caratteristica. Funziona abbastanza bene, anche se non sono sicuro perché devo mandare il metodo setter invece di utilizzarlo normalmente. Non sembrava funzionare anche se così questo farà:)

  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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top