Wie eine Rails mixin schreiben, die über Modell, Controller umfasst, und Ausblick
-
09-06-2019 - |
Frage
In dem Bemühen, Code-Duplizierung in meiner kleinen Rails-Anwendung zu reduzieren, hat mich zwischen meinen Modellen in seinem eigenen separaten Modul auf dem Erhalten gemeinsamen Code gearbeitet, so weit so gut.
Das Modell Zeug ist ziemlich einfach, ich muss nur das Modul umfassen am Anfang steht, z.
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
Dies funktioniert gut, jetzt aber ich werde einige Controller und View-Code haben, die auch gemeinsam zwischen diesen Modellen sein werden, so weit ich habe das für meine sendbar Sachen:
# 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
Grundsätzlich plane ich auf nur ein sendbar ::-Controller gehören zu tun, und sendbar :: View (oder das äquivalent) für die Steuerung und die Aussicht, aber gibt es einen sauberen Weg, dies zu tun? Ich bin nach einem ordentlichen Weg, um ein Bündel von gemeinsamem Code zwischen meinem Modell, Controller und Ansicht zu haben.
Edit: Nur um zu klären, hat dies nur über 2 oder 3 Modelle gemeinsam genutzt werden
.Lösung
Sie könnten pluginize es (Verwendung / script erzeugen Plugin).
Dann in Ihrem init.rb nur so etwas wie:
ActiveRecord::Base.send(:include, PluginName::Sendable)
ActionController::Base.send(:include, PluginName::SendableController)
Und zusammen mit Ihrem self.included, die sollte gut funktionieren.
Sehen Sie sich einige der acts_ * Plug-Ins aus, es ist ein ziemlich häufiges Muster ( http://github.com/technoweenie/acts_as_paranoid/tree/master/init.rb , Check Zeile 30)
Andere Tipps
Wenn dieser Code muss für alle Modelle und alle Regler erhalten hinzugefügt, könnten Sie immer wie folgt vor:
# maybe put this in environment.rb or in your module declaration
class ActiveRecord::Base
include Iso
end
# application.rb
class ApplicationController
include Iso
end
Wenn Sie Funktionen von diesem Modul zur Verfügung, um die Ansichten benötigen, können Sie sie mit helper_method
Erklärungen in application.rb individuell aussetzen könnten.
Wenn Sie die Plug-Route gehen, überprüfe heraus Rails-Engines , die dazu bestimmt ist, zu erweitern Plug-Semantik zu Controllern und Views in einer klaren Art und Weise.