문제

내 작은 Rails 앱에서 코드 중복을 줄이기 위한 노력의 일환으로, 나는 내 모델 간의 공통 코드를 별도의 모듈로 가져오는 작업을 해왔고 지금까지는 매우 훌륭했습니다.

모델 작업은 상당히 쉽습니다. 처음에 모듈을 포함하면 됩니다. 예:

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

이것은 잘 작동하지만 이제는 이러한 모델 간에도 공통적으로 사용되는 일부 컨트롤러와 뷰 코드를 갖게 될 것입니다. 지금까지 보낼 수 있는 항목은 다음과 같습니다.

# 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

기본적으로 저는 컨트롤러와 뷰에 대해 Sendable::Controller 및 Sendable::View(또는 이에 상응하는 항목)를 포함할 계획입니다. 하지만 이를 수행하는 더 깔끔한 방법이 있습니까?저는 모델, 컨트롤러, 뷰 사이에 공통 코드를 배치하는 깔끔한 방법을 찾고 있습니다.

편집하다:명확히 하자면, 이는 2~3개의 모델 간에 공유되어야 합니다.

도움이 되었습니까?

해결책

플러그인을 사용할 수 있습니다(스크립트/플러그인 생성 사용).

그런 다음 init.rb에서 다음과 같이 하십시오:

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

그리고 당신의 self.include와 함께 그것은 잘 작동할 것입니다.

일부 act_* 플러그인을 확인해 보세요. 꽤 일반적인 패턴입니다(http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb, 30행을 확인하세요)

다른 팁

해당 코드를 모든 모델과 모든 컨트롤러에 추가해야 하는 경우 언제든지 다음을 수행할 수 있습니다.

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

# application.rb
class ApplicationController
  include Iso
end

뷰에서 사용할 수 있는 이 모듈의 기능이 필요한 경우 다음을 사용하여 개별적으로 노출할 수 있습니다. helper_method application.rb의 선언.

플러그인 경로로 이동하는 경우 체크아웃하세요. 레일 엔진, 이는 플러그인 의미를 컨트롤러와 뷰로 명확하게 확장하기 위한 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top