¿Cuál es el código predeterminado para has_many mayor: unirse a través de la asignación de carriles?
-
16-09-2019 - |
Pregunta
Tengo un has_many básico: a través de relación que es bi-direccional:
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
Estoy queriendo asignar calendarios a un evento con la función básica que calendar_ids=
has_many: a través de conjuntos hacia arriba, sin embargo, quiero anular esta función para añadir un poco de magia extra. He tenido una mirada a través de la fuente de los carriles y no puedo encontrar el código para esta función. Me pregunto si alguien me podría apuntar a la misma. Voy a continuación, anularlo para esta clase de añadir las cosas que yo quiero:)
Solución
Puede encontrar el código fuente en el lib/active_record/associations.rb
archivo en línea de 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
Definitivamente debe evitar sobrescribir este método para agregar tales cosas mágicas. Raíles ya es "demasiada magia" a veces. Yo sugeriría para crear un atributo virtual con toda su lógica personalizada por varias razones:
-
métodos
- algunos otros carriles podrían basarse en la aplicación por defecto
- que se basan en una API específica que pudiera ir a cambiar en el futuro versiones ActiveRecord
Otros consejos
Después de un poco de una búsqueda he encontrado:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/collection_accessor_methods
No se parecía a lo que pensaba que se vería así, así que por eso probablemente me lo perdí. Terminé anulando el calendarios = método en lugar del método calendar_ids = y todo funciona bien.
En respuesta a la respuesta anterior, solía alias_method_chain para anular el colocador defecto y añadir mi función. Funciona bastante bien, aunque no estoy seguro de por qué tengo que enviar el método setter en lugar de usar normalmente. No parecía que trabajar, así que esto va a hacer:)
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