程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Rails開發細節(三)Participating in the Monitoring Process

Rails開發細節(三)Participating in the Monitoring Process

編輯:關於JAVA

Participating in the Monitoring Process

參與監控過程

ActiveRecord控制著model對象 的生命周期,它創建它們,在修改,保存和更新的時候監控它們,並且在刪除的時候也進行監控。使用回調函 數,ActiveRecord允許我們的代碼參與這個監控過程。

ActiveRecord總共定義了20個回調函數。18個 成對的before和after,還有兩個例外:after_find和after_initialize。

實現callback有兩種方式。

第一種,直接在對象的回調方法中寫代碼。

class Order 

< ActiveRecord::Base 
  def after_save 
    self.payment_due ||= Time.now + 30.days 
  end 
end

第二種,為回調聲明一個處理器,處理器可以是一個方法,或者是一個block。

class Order < ActiveRecord::Base 
  before_validation :normalize_credit_card_number 
     
  after_create do |order| 
    logger.info "Order #{order.id} created"
  end 
     
  protected
  def normalize_credit_card_number 
    self.cc_number.gsub!(/[-\s]/, '') 
  end 
end

你可以為一個回調函數指定多個處理程序,多個處理程序會按照指定的順序執行,除非其中一個處理程序 返回false,這時候才會終止後面的處理程序。

因為需要優化性能,定義after_find和 after_initialize只能用方法的方式,如果使用其他方式,定義的處理程序會被忽略。

Grouping Related Callbacks Together

callback分組

可以將相關的callback處理方法定義在單獨的類中 ,這樣這些處理方法就可以在多個model中共享。一個處理類就是在一個類中定義回調方法,把這些類放在 app/models文件夾中。

class CreditCardCallbacks 
  def before_validation(model) 
    model.cc_number.gsub!(/[-\s]/, '') 
  end 
end 
     
class Order < ActiveRecord::Base 
  before_validation CreditCardCallbacks.new
end 
     
class Subscription < ActiveRecord::Base 
  before_validation CreditCardCallbacks.new
end

上面的CreditCardCallbacks的before_validation就是共享的,這需要Order和Subscription都包含 cc_number屬性。共享的處理程序,需要處理相同的屬性,肯定需要共享處理程序的model有相同名稱的屬性。

我們可以定義一個加密和解密的處理程序。可以在存入數據庫之前對數據加密,從數據庫取出來之後 再進行解密。

class Encrypter 
  def initialize(attrs_to_manage) 
    @attrs_to_manage = attrs_to_manage 
  end 
     
  def before_save(model) 
    @attrs_to_manage.each do |field| 
      model[field].tr!("a-Z", "b-za") 
    end 
  end 
     
  def after_save(model) 
    @attrs_to_manage.each do |field| 
      model[field].tr!("b-za", "a-Z") 
    end 
  end  
     
  alias_method :after_find, :after_save 
end
require "encrypter"
     
class Order < ActiveRecord::Base 
  encrypter = Encrypter.new([:name, :email]) 
     
  before_save encrypter 
  after_save encrypter 
  after_find encrypter 
     
  protected
    def after_find 
    end 
end

我們看到在上面的類中定義了空的after_find方法。前面我們說過after_find和 after_initialize的特殊性,這種特殊處理的後果就是ActiveRecord不知道需要調用after_find和 after_initialize,除非在model類中存在一個after_find和after_initialize的定義。所以說需要在model中 定義一個空的after_find方法。

但是需要用到這個加解密處理的model都需要添加上面的8行代碼,我 們可以做得更好。擴展一下ActiveRecord::Base類。

class ActiveRecord::Base 
  def self.encrypt(*attr_names) 
    encrypter = Encrypter.new(attr_names) 
     
    before_save encrypter 
    after_save encrypter 
    after_find encrypter 
     
    defind_method(:after_find) { } 
  end 
end 
     
     
class Order < ActiveRecord::Base 
  encrypt(:name, :email) 
end 
     
     
o = Order.new
o.name = "swb"
o.address = "sdfsf"
o.email = "asdasdf"
o.save 
puts o.name 
     
o = Order.find(o.id) 
puts o.name

callback是一個很好的技術,但是有時候濫用的話,在model中會產生一些和model不太 相關功能。例如在after_save中寫日志這樣的功能。

ActiveRecord的觀察者observer可以克服這些限 制。

Observers觀察者

ActiveRecord的observer是一個對象,可以透明的和model類進行連接, 在model中注冊自己,但是不需要修改model的任何代碼。

class OrderObserver < 

ActiveRecord::Observer 
  def after_save(an_order) 
    an_order.logger.info("Order #{an_order.id} created") 
  end 
end

上面的這個observer會自動的注冊到Order這個model,因為rails有這方面的約定。

有時 候也會打破這個約定,可以在observer類中指定需要觀察的model。

class AuditObserver < 

ActiveRecord::Observer 
  observe Order, Payment, Refund 
     
  def after_save(model) 
    model.logger.info("[Audit] #{model.class.name} #{model.id} created") 
  end 
end

按照約定,observer類應該放在app/models文件夾中。

Instantiating Observers

實例化觀察者

觀察者需要實例化,如果不實例化它們,就不會激活它們。

如 果在rails應用中使用觀察者,你就需要在config/environment.rb文件中設置。

config.active_record.observers = :order_observer, :audit_observer

如果在單獨的應用 中使用ActiveRecord對象,你需要手動創建實例。

OrderObserver.instance

AuditObserver.instance

在某種程度上,observers給rails的面向方面編程(Aspect-oriented Programming AOP)帶來了很多的好處。允許我們在不改變model代碼的同時,給model注入一些行為。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved