Qual è il codice di default per has_many di massa: attraverso unirsi incarico in rotaie?
-
16-09-2019 - |
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:)
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
- alcune altre rotaie potrebbero contare sulla implementazione di default
- 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