Pergunta

Ok, então eu tenho de refatoração de código meu em meu pequeno Trilhos de app em um esforço para remover a duplicação, e, em geral, facilitar minha vida (como eu gosto de uma vida fácil).Parte desta refatoração, tem sido a de mover o código que é comum a dois dos meus modelos para um módulo que eu possa incluir onde eu preciso.

Tão longe, tão bom.Parece que vai funcionar, mas eu acabei de bater um problema que eu não tenho certeza de como dar a volta.O módulo (que eu tenho chamado de enviável), é apenas vai ser o código que trata de fax, e-mail ou imprimir um PDF do documento.Assim, por exemplo, eu tenho uma ordem de compra, e eu tenho Interno de Pedidos de Vendas (imaginação abreviado para ISO).

O problema conquistei, é que eu precisava de algumas variáveis inicializadas (inicializado para as pessoas que não soletra corretamente :P ) depois que o objeto é carregado, por isso estou usando o after_initialize gancho.Nenhum problema...até eu começar a adicionar alguns mais mixins.

O problema que eu tenho, é que eu possa ter uma after_initialize em qualquer um dos meus mixins, então eu preciso incluir super chamada para começar, certifique-se de que os outros mixin after_initialize chamadas de ser chamada.O que é ótimo, até eu acabar chamando de super e eu recebo um erro, porque não há super para chamar.

Aqui está um pequeno exemplo, no caso eu não tenha sido bastante confuso:

class Iso < ActiveRecord::Base
  include Shared::TracksSerialNumberExtension
  include Shared::OrderLines
  extend  Shared::Filtered
  include Sendable::Model

  validates_presence_of   :customer
  validates_associated    :lines

  owned_by                :customer
  order_lines             :despatched # Mixin

  tracks_serial_numbers   :items  # Mixin

  sendable :customer                      # Mixin

  attr_accessor :address

  def initialize( params = nil )
    super
    self.created_at ||= Time.now.to_date
  end
end

Assim, se cada um dos mixins ter um after_initialize convocação, com super chamar, como eu posso parar com isso última super chamada de elevar o erro?Como posso testar o super existe um método antes de eu chamá-lo?

Foi útil?

Solução

Você pode usar esse:

super if defined?(super)

Aqui está um exemplo:

class A
end

class B < A
  def t
    super if defined?(super)
    puts "Hi from B"
  end
end

B.new.t

Outras dicas

Você já tentou alias_method_chain?Basicamente você pode acorrentado todos os seus after_initialize chamadas.Ele age como um decorador:cada novo método adiciona uma nova camada de funcionalidade e passa o controle para o "substituído" método para fazer o resto.

Incluindo a classe (a única coisa que se herda ActiveRecord::Base, que, neste caso, é Iso) poderia definir o seu próprio after_initialize, assim , qualquer solução diferente alias_method_chain (ou outros aliasing que guarda o original) riscos de substituição de código.@Orion Edwards solução é a melhor que eu pode vir acima com.Existem outros, mas eles são longe mais hackish.

alias_method_chain também tem a vantagem de criar o nome versões do after_initialize método, o que significa que você pode personalizar a ordem de chamada nos raros casos em que é importante.Caso contrário, você está à mercê de qualquer ordem, incluindo a classe inclui os mixins.

mais tarde:

Eu postei uma pergunta para o ruby-on-rails-core lista de discussão sobre a criação de padrão vazio implementações de todas as chamadas de retorno.O processo de salvamento verifica-los todos de qualquer maneira, então eu não vejo por que não deveria estar lá.A única desvantagem é a criação de extra pilha vazia quadros, mas que é muito baixo em todos os conhecidos de implementação.

Você pode apenas jogar uma rápida condicional lá:

super if respond_to?('super')

e você deve ser fino - sem adição de métodos inúteis;agradável e limpo.

Em vez de verificar se o super existe um método, você pode apenas definir

class ActiveRecord::Base
    def after_initialize
    end
end

Isso funciona no meu teste, e não deve quebrar qualquer código existente, porque todas as suas outras classes que definem será apenas silenciosamente substituindo este método de qualquer maneira

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top