2008-09-16 3 views
5

내 작은 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 

, 지금은하지만, 내가 어떤 컨트롤러와 뷰 코드를하겠습니다을 즉, 지금까지 내 sendable 물건이있을뿐만 아니라, 이러한 모델에 공통 될 것 :

# 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 :: 컨트롤러 및 Sendable ::보기를 포함하고있는에 계획입니다

(또는 이에 상응하는) 컨트롤러와 뷰를위한 것이지만, 더 깨끗한 방법입니다 이? 내 모델, 컨트롤러 및 뷰간에 일련의 공통 코드를 사용하는 깔끔한 방법을 따랐습니다.

편집 : 분명히하기 위해, 이것은 단지 2 또는 3 모델을 통해 공유되어야합니다. 개별적으로

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

# application.rb 
class ApplicationController 
    include Iso 
end 

당신의 의견에 사용할 수있는이 모듈에서 기능이 필요한 경우, 당신이 그들을 노출 수 :이 코드는 모든 모델과 모든 컨트롤러에 추가됩니다 할 필요가있는 경우

답변

7

플러그인 할 수 있습니다 (스크립트/생성 플러그인 사용). 당신의 init.rb에서 다음

는 그런 짓을 :

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

그리고 잘 작동합니다 당신의 self.included과 함께

.

체크 아웃 acts_의 일부를 * 플러그인, 그것은 매우 일반적인 패턴이다 (http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb, 체크 라인 (30)) 당신이 플러그인 경로를 이동 할 경우에 플러그인 의미를 확장하기위한 것입니다 Rails-Engines을 체크 아웃 할

+0

Hoyhoy 's는 완벽하게 괜찮은 편이지만이 답변을 선택했습니다. 왜냐하면 Hoyhoy 's는 내가 더 잘하고있는 것에 적합하기 때문입니다. – Mike

+0

정말 똑같습니다. 이것은 더 나은 구문입니다. – hoyhoy

6

, 당신은 항상이 다음을 수행 할 수 application.rb의 선언은 helper_method입니다.

+0

이것은 아마도 내가 끝낼 것입니다. 내 함수 등이 이름 충돌을 일으키지 않는 한 문제가되어서는 안됩니다. – Mike

1

컨트롤러와 뷰는 명확한 방법으로 제공됩니다.

+0

나는 빠른 견해를 보았다. 아마 나의 문제를 해결할 수있을 것이다. 그러나 나는 아직 확신 할 수 없다. – Mike

관련 문제