Pregunta

En un esfuerzo por reducir la duplicación de código en mi pequeña aplicación Rails, he estado trabajando para obtener código común entre mis modelos en su propio módulo separado, hasta ahora todo bien.

El modelo es bastante fácil, sólo tengo que incluir el módulo al principio, por ejemplo:

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

  validates_presence_of   :customer
  validates_associated    :lines

  owned_by :customer

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

  def after_initialize
  end

  order_lines             :despatched

  # tracks_serial_numbers   :items
  sendable :customer

  def created_at=( date )
    write_attribute( :created_at, Chronic.parse( date ) )
  end
end

Esto está funcionando bien, sin embargo, ahora voy a tener un código de controlador y de vista que también será común entre estos modelos, hasta ahora tengo esto para mis cosas que se pueden enviar:

# This is a module that is used for pages/forms that are can be "sent"
# either via fax, email, or printed.
module Sendable
  module Model
    def self.included( klass )
      klass.extend ClassMethods
    end

    module ClassMethods
      def sendable( class_to_send_to )
        attr_accessor :fax_number,
                      :email_address,
                      :to_be_faxed,
                      :to_be_emailed,
                      :to_be_printed

        @_class_sending_to ||= class_to_send_to

        include InstanceMethods
      end

      def class_sending_to
        @_class_sending_to
      end
    end # ClassMethods

    module InstanceMethods
      def after_initialize( )
        super
        self.to_be_faxed    = false
        self.to_be_emailed  = false
        self.to_be_printed  = false

        target_class = self.send( self.class.class_sending_to )
        if !target_class.nil?
          self.fax_number     = target_class.send( :fax_number )
          self.email_address  = target_class.send( :email_address )
        end
      end
    end
  end # Module Model
end # Module Sendable

Básicamente, estoy planeando simplemente incluir Sendable::Controller y Sendable::View (o el equivalente) para el controlador y la vista, pero, ¿hay una manera más limpia de hacer esto?Busco una manera clara de tener un montón de código común entre mi modelo, controlador y vista.

Editar:Solo para aclarar, esto solo debe compartirse entre 2 o 3 modelos.

¿Fue útil?

Solución

Puede complementarlo (usar script/generar complemento).

Luego en tu init.rb simplemente haz algo como:

ActiveRecord::Base.send(:include, PluginName::Sendable)
ActionController::Base.send(:include, PluginName::SendableController)

Y junto con usted mismo, incluido, eso debería funcionar bien.

Echa un vistazo a algunos de los complementos acts_*, es un patrón bastante común (http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb, marque la línea 30)

Otros consejos

Si es necesario agregar ese código a todos los modelos y todos los controladores, siempre puede hacer lo siguiente:

# maybe put this in environment.rb or in your module declaration
class ActiveRecord::Base
  include Iso
end

# application.rb
class ApplicationController
  include Iso
end

Si necesitara funciones de este módulo disponibles para las vistas, podría exponerlas individualmente con helper_method declaraciones en application.rb.

Si sigue la ruta del complemento, consulte Motores-rieles, que están destinados a extender la semántica de los complementos a Controladores y Vistas de una manera clara.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top