6

私の小さな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つのモデル間で共有する必要があります。

4

3 に答える 3

7

そのコードをすべてのモデルとすべてのコントローラーに追加する必要がある場合は、いつでも次のことを実行できます。

# 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の宣言を使用してそれらを個別に公開できます。

于 2008-09-16T02:35:38.587 に答える
7

プラグイン化できます(スクリプトを使用/プラグインを生成)。

次に、init.rb で次のようにします。

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

そして、あなたの self.included とともに、それはうまくいくはずです。

act_* プラグインのいくつかを確認してください。これはかなり一般的なパターンです ( http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb、30 行目を確認してください)。

于 2008-09-16T03:36:54.057 に答える
1

プラグインルートを使用する場合は、Rails-Enginesを確認してください。これは、プラグインのセマンティクスをコントローラーとビューに明確に拡張することを目的としています。

于 2008-09-16T04:34:14.387 に答える