Question

I ai un has_many de base: par relation qui est bi-directionnel:

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

Je suis désireux d'attribuer des calendriers à un événement avec la fonction de base qui calendar_ids= has_many: à travers des ensembles en place, cependant, je veux passer outre cette fonction pour ajouter un peu de magie supplémentaire. J'ai eu un coup d'oeil à travers la source de rails et ne peut pas trouver le code pour cette fonction. Je me demande si quelqu'un pouvait me pointer vers elle. Je vais donc passer outre pour cette classe d'ajouter les choses que je veux:)

Était-ce utile?

La solution

Vous pouvez trouver le code source dans le fichier lib/active_record/associations.rb à la ligne 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

Vous devez absolument éviter d'écraser comme cette méthode pour ajouter des choses magiques. Rails est déjà « trop magique » parfois. Je suggère de créer un attribut virtuel avec toute votre logique personnalisée pour plusieurs raisons:

  1. d'autres méthodes de rails peuvent compter sur l'implémentation par défaut
  2. vous comptez sur une API spécifique qui pourrait va changer à l'avenir versions ActiveRecord

Autres conseils

Après un peu de chasse je l'ai trouvé:

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

Il ne ressemblait pas à ce que je pensais que ce serait ressembler à, si c'est pourquoi je probablement raté. J'ai fini par redéfinissant la méthode calendriers = au lieu de la calendar_ids = méthode et tout fonctionne bien.

En réponse à la réponse ci-dessus, j'ai utilisé alias_method_chain pour remplacer le dispositif de réglage par défaut et ajouter ma fonction. Fonctionne très bien, mais je ne sais pas pourquoi je dois envoyer le poseur de méthode au lieu de simplement l'utiliser normalement. Il ne semble pas fonctionner bien si cela va faire:)

  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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top