如何编写跨越模型,控制器和视图的Rails mixin

为了减少我的小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 ,它们旨在以清晰的方式将插件语义扩展到控制器和视图。