Was ist der Standardcode für Massen has_many: durch beitreten Zuordnung in Schienen?
-
16-09-2019 - |
Frage
Ich habe eine grundlegende has_many: durch Beziehung, die bi-direktionale ist:
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
Ich bin zu wollen Kalender auf ein Ereignis mit der Grund calendar_ids=
Funktion zuweisen, die has_many: durch einrichtet, aber ich möchte diese Funktion außer Kraft setzen einige zusätzliche Magie hinzuzufügen. Ich habe einen Blick durch die Schienen Quelle hatte und nicht den Code für diese Funktion finden. Ich frage mich, wenn mich jemand darauf hinweisen könnte. Ich werde außer Kraft setzen es dann für diese Klasse das Material hinzuzufügen, das ich will:)
Lösung
Sie können den Quellcode in der Datei lib/active_record/associations.rb
in Zeile 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
Sie sollten auf jeden Fall vermeiden, so diese Methode zu überschreiben magische Sachen hinzuzufügen. Rails ist bereits „zu viel Magie“ manchmal. Ich würde vorschlagen, ein virtuelles Attribut mit allen kundenspezifische Logik aus mehreren Gründen zu erstellen:
- einige andere Schienen Methoden könnten auf der Standardimplementierung verlassen
- setzen Sie auf eine bestimmte API, die in zukünftigen Versionen Active könnte sich ändern
Andere Tipps
Nach etwas einer Jagd ich es gefunden:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/collection_accessor_methods
Es sah nicht so aus, was ich dachte, es aussehen würde, ist also, warum ich es wohl verpasst. Ich beendete die Kalender = Methode anstelle der calendar_ids = Methode überschrieben und alles funktioniert gut.
Als Reaktion auf die Antwort oben, habe ich alias_method_chain die Standard-Setter außer Kraft zu setzen und meine Funktion hinzuzufügen. Funktioniert ganz gut, obwohl ich nicht sicher bin, warum ich habe die Methode Setter zu senden, anstatt nur sie normalerweise verwendet wird. Es ist nicht zu funktionieren scheint aber so wird dies tun:)
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