Pergunta

Eu tenho um has_many básica: através da relação que é bi-direcional:

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

Eu estou querendo calendários atribuir a um evento com a função calendar_ids= básico que has_many: através de conjuntos para cima, no entanto, eu quero substituir essa função para adicionar um pouco de magia extra. Eu tive um olhar através da fonte de trilhos e não pode encontrar o código para esta função. Eu estou querendo saber se alguém poderia me apontar para ele. Então eu vou substituí-lo para esta classe para adicionar as coisas que eu quero:)

Foi útil?

Solução

Você pode encontrar o código-fonte no lib/active_record/associations.rb arquivo na linha 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

Você deve definitivamente evitar sobrescrever tal, este método para adicionar coisas mágicas. Rails já é "muito mágico" às vezes. Gostaria de sugerir para criar um atributo virtual com toda a lógica o seu costume por várias razões:

  1. alguns outros métodos trilhos pode contar com a implementação padrão
  2. você contar com uma API específica que o poder vai mudar em futuras versões do Active Record

Outras dicas

Depois de um pouco de uma caça eu achei:

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

Ele não se parecia com o que eu pensava que seria parecido, é por isso que eu provavelmente perdeu. Eu acabei substituindo o calendários = método em vez do calendar_ids = método e tudo funciona bem.

Em resposta à resposta acima, eu usei alias_method_chain para substituir o setter padrão e adicionar o meu recurso. Funciona muito bem, embora eu não sei por que eu tenho que enviar o setter método em vez de apenas utilizá-lo normalmente. Ele não parecia trabalho embora, que vai fazer:)

  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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top