[英]How to write a Rails mixin that spans across model, controller, and view
In an effort to reduce code duplication in my little Rails app, I've been working on getting common code between my models into it's own separate module, so far so good. 为了减少我的小Rails应用程序中的代码重复,我一直在努力将我的模型之间的公共代码添加到它自己的独立模块中,到目前为止一直很好。
The model stuff is fairly easy, I just have to include the module at the beginning, eg: 模型的东西相当简单,我只需要在开头包含模块,例如:
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 working fine, now however, I'm going to have some controller and view code that's going to be common between these models as well, so far I have this for my sendable stuff: 这工作正常,但是,现在我将要有一些控制器和视图代码,这些代码在这些模型之间也是常见的,到目前为止,我有这个用于我的可发送内容:
# 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
Basically I'm planning on just doing an include Sendable::Controller, and Sendable::View (or the equivalent) for the controller and the view, but, is there a cleaner way to do this? 基本上我打算只为控制器和视图做一个包含Sendable :: Controller和Sendable :: View(或等效的),但有没有更简洁的方法呢? I 'm after a neat way to have a bunch of common code between my model, controller, and view.
我正在以一种巧妙的方式在我的模型,控制器和视图之间拥有一堆通用代码。
Edit: Just to clarify, this just has to be shared across 2 or 3 models. 编辑:只是为了澄清,这只需要在2或3个模型中共享。
You could pluginize it (use script/generate plugin). 你可以插件(使用脚本/生成插件)。
Then in your init.rb just do something like: 然后在init.rb中执行以下操作:
ActiveRecord::Base.send(:include, PluginName::Sendable)
ActionController::Base.send(:include, PluginName::SendableController)
And along with your self.included that should work just fine. 并伴随着你的自我。包括应该工作得很好。
Check out some of the acts_* plugins, it's a pretty common pattern ( http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb , check line 30) 查看一些acts_ *插件,这是一个非常常见的模式( http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb ,检查第30行)
If that code needs to get added to all models and all controllers, you could always do the following: 如果需要将该代码添加到所有模型和所有控制器,则可以始终执行以下操作:
# maybe put this in environment.rb or in your module declaration
class ActiveRecord::Base
include Iso
end
# application.rb
class ApplicationController
include Iso
end
If you needed functions from this module available to the views, you could expose them individually with helper_method
declarations in application.rb. 如果您需要视图可用的此模块中的函数,则可以使用
helper_method
声明单独公开它们。
如果你去插件路线,请查看Rails-Engines ,它们旨在以清晰的方式将插件语义扩展到控制器和视图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.