簡體   English   中英

如何編寫跨越模型,控制器和視圖的Rails mixin

[英]How to write a Rails mixin that spans across model, controller, and view

為了減少我的小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)

並伴隨着你的自我。包括應該工作得很好。

查看一些acts_ *插件,這是一個非常常見的模式( 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聲明單獨公開它們。

如果你去插件路線,請查看Rails-Engines ,它們旨在以清晰的方式將插件語義擴展到控制器和視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM