2010-09-12 32 views
42

Tôi đã thử đọc qua các bài đăng trên blog khác nhau cố gắng giải thích alias_method_chain và lý do sử dụng nó và không sử dụng nó. Đặc biệt, tôi phía dưới nghe theo:Ruby on Rails: alias_method_chain, chính xác nó làm gì?

http://weblog.rubyonrails.org/2006/4/26/new-in-rails-module-alias_method_chain

http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/

tôi vẫn không thấy bất kỳ sử dụng thực tế cho alias_method_chain. Có ai có thể giải thích một vài điều.

1 - nó vẫn được sử dụng?
2 - khi nào bạn sử dụng alias_method_chain và tại sao?

Trả lời

90

1 - nó vẫn được sử dụng?

Dường như có, alias_method_chain()still used in Rails (kể từ phiên bản 3.0.0).

2 - khi nào bạn sử dụng alias_method_chain và tại sao?

(Lưu ý:. sau chủ yếu dựa vào các cuộc thảo luận của alias_method_chain() trong Metaprogramming Ruby bởi Paolo Perrotta, mà là một cuốn sách tuyệt vời mà bạn nên có được bàn tay của bạn trên)

Hãy bắt đầu với ví dụ cơ bản:

class Klass 
    def salute 
    puts "Aloha!" 
    end 
end 

Klass.new.salute # => Aloha! 

Giả sử chúng tôi muốn bao quanh Klass#salute() với hành vi ghi nhật ký. Chúng ta có thể làm những gì Perrotta gọi một xung quanh bí danh:

class Klass 
    def salute_with_log 
    puts "Calling method..." 
    salute_without_log 
    puts "...Method called" 
    end 

    alias_method :salute_without_log, :salute 
    alias_method :salute, :salute_with_log 
end 

Klass.new.salute 
# Prints the following: 
# Calling method... 
# Aloha! 
# ...Method called 

Chúng tôi định nghĩa một phương pháp mới được gọi là salute_with_log() và aliased nó để salute(). Mã được sử dụng để gọi salute() vẫn hoạt động nhưng cũng có hành vi ghi nhật ký mới.Chúng tôi cũng xác định một bí danh với bản gốc salute(), vì vậy chúng tôi vẫn có thể chào mà không cần đăng nhập:

Klass.new.salute_without_log # => Aloha! 

Vì vậy, salute() bây giờ được gọi salute_without_log(). Nếu chúng tôi muốn đăng nhập, chúng tôi có thể gọi salute_with_log() hoặc salute(), là bí danh của cùng một phương pháp. Bối rối? Tốt!

Theo Perrotta, loại xung quanh bí danh là rất phổ biến trong Rails:

Nhìn vào một ví dụ khác của Rails giải quyết vấn đề theo cách riêng của nó. Một vài các phiên bản trước, các mã Rails chứa nhiều trường hợp các thành ngữ giống nhau: một Khoảng Bí danh (155) được sử dụng để thêm một tính năng đến một phương pháp, và phiên bản cũ của phương pháp này được đổi tên thành một cái gì đó như method_without_feature(). Ngoài các tên phương thức , thay đổi mỗi lần , mã đã thực hiện điều này là luôn giống nhau, được nhân đôi trên địa điểm. Trong hầu hết các ngôn ngữ, bạn không thể tránh loại trùng lặp đó. Trong Ruby, bạn có thể rắc một số phép thuật lập trình metaprogram trên mẫu của bạn và giải nén nó vào phương thức riêng của nó ... và do đó được sinh ra alias_method_chain().

Nói cách khác, bạn cung cấp các phương pháp ban đầu, foo(), và các phương pháp nâng cao, foo_with_feature(), và bạn kết thúc với ba phương pháp: foo(), foo_with_feature(), và foo_without_feature(). Hai cái đầu tiên bao gồm tính năng, trong khi thứ ba thì không. Thay vì sao chép các bí danh này xung quanh, alias_method_chain() provided by ActiveSupport thực hiện tất cả bí danh cho bạn.

+32

+1 để nói "Bối rối? Tốt!" – jperelli

+11

và bổ sung nhỏ: vì vậy bây giờ chúng ta có thể chỉ cần gõ '' 'alias_method_chain: foo,: feature''' và chúng ta sẽ có 3 phương thức:' '' foo''', '' 'foo_with_feature''',' '' foo_without_feature '' 'được đặt tên đúng như * Yases Sulaiman * mô tả trước – freemanoid

+2

" Bất kỳ công nghệ tiên tiến nào cũng không thể phân biệt được với phép thuật. " Arthur C. Clarke –

4

Tôi không chắc liệu nó có mất phong cách với Rails 3 hay không, nhưng nó vẫn được sử dụng tích cực trong các phiên bản trước đó.

Bạn sử dụng nó để tiêm một số chức năng trước (hoặc sau) một phương thức được gọi, mà không sửa đổi bất kỳ địa điểm nào gọi phương thức đó. Xem ví dụ sau:

module SwitchableSmtp 
    module InstanceMethods 
    def deliver_with_switchable_smtp!(mail = @mail) 
     unless logger.nil? 
     logger.info "Switching SMTP server to: #{custom_smtp.inspect}" 
     end 
     ActionMailer::Base.smtp_settings = custom_smtp unless custom_smtp.nil? 
     deliver_without_switchable_smtp!(mail = @mail) 
    end 
    end 
    def self.included(receiver) 
    receiver.send :include, InstanceMethods 
    receiver.class_eval do 
     alias_method_chain :deliver!, :switchable_smtp 
    end 
    end 
end 

Đó là một sự bổ sung để ActionMailer để cho phép trao đổi ra các thiết lập SMTP trên mỗi cuộc gọi đến deliver!. Bằng cách gọi alias_method_chain, bạn có thể xác định phương thức deliver_with_switchable_smtp!, trong đó bạn thực hiện công cụ tùy chỉnh của mình và gọi deliver_without_switchable_smtp! từ đó khi bạn hoàn tất.

alias_method_chain bí danh số deliver! cũ cho phương thức tùy chỉnh mới của bạn, vì vậy phần còn lại của ứng dụng của bạn thậm chí không biết deliver! hiện cũng là công cụ tùy chỉnh của bạn.

+0

nên không 'alias_method_chain: cung cấp !,: switchable_smtp' được 'alias_method_chain: cung cấp !,: deliver_with_switchable_smtp'!? – Waseem

+0

Không đúng. – Waseem

2

là nó có được sử dụng không?

Seems so. Thực tiễn phổ biến trong số các nhà phát triển Rails

khi nào bạn sử dụng alias_method_chain và tại sao?

Mặc dù có cảnh báo, alias_method_chain vẫn là chiến lược chính được sử dụng khi tiêm hàm vào phương thức hiện có, ít nhất là trong Rails 2.x và được nhiều người mở rộng. Yehuda nên loại bỏ alias_method_chain từ đường ray 3.0 để nói từ bài viết và bình luận của anh trong vé Rails. Nó vẫn được sử dụng bởi nhiều tiện ích mở rộng thêm hành vi tùy chỉnh tại các điểm nhất định của việc thực hiện, chẳng hạn như nhật ký, trình báo lỗi, đo điểm chuẩn, phun dữ liệu, v.v.

IMO, cách thay thế tốt nhất là bao gồm mô-đun, do đó bạn có trang trí cho phái đoàn. (Ví dụ: làm theo ví dụ 4 trong số this post). Bằng cách đó, bạn có thể thay đổi các đối tượng ngay cả khi bạn muốn, mà không làm ô nhiễm các phương thức của lớp. Nhược điểm của việc này là chuỗi tra cứu phương thức tăng cho mỗi mô-đun mà bạn tiêm, nhưng đây là những mô-đun nào cho dù sao.

Câu hỏi rất thú vị, sẽ theo dõi những gì người khác nghĩ về nó.