2011-10-17 35 views
35

Tôi đang phát triển một ứng dụng Rails mới dựa trên một ứng dụng tương tự hiện có. Trong ứng dụng cũ của tôi, tôi có lớp Coupon, rất giống với Ticket trong ứng dụng mới của tôi. Tôi muốn sử dụng lại tất cả các mã trong Coupon, nhưng với một tên lớp mới.Bí danh lớp trong Ruby

Kể từ khi tái cấu trúc là cồng kềnh trong Rails, tôi tự hỏi có cách nào để tạo bí danh cho một lớp trong Ruby (tương tự như bí danh cho thuộc tính và phương pháp).

+14

Còn thừa kế thì sao? Một cái gì đó như thế này: class Coupon WarHog

Trả lời

79

Lớp don' t có tên trong Ruby. Chúng chỉ là các đối tượng được gán cho các biến, giống như bất kỳ đối tượng nào khác. Nếu bạn muốn tham khảo một lớp thông qua một biến khác nhau, gán nó vào một biến khác nhau:

Foo = String 
+0

Jörg, cảm ơn vì viên ngọc đó: nó hoàn toàn hiển nhiên, tôi vẫn chưa bao giờ nghĩ về nó trước đây! – p4010

+0

Cảm ơn, Jorg. Đó là giải pháp hoàn toàn hợp lý, nhưng đáng ngạc nhiên. :) – AdamNYC

+3

Nó không thay đổi. Nó không đổi (tất cả các mã định danh bắt đầu bằng chữ hoa là hằng số). – Hauleth

2

Tôi đồng ý với warhog, nhiều hơn hoặc ít hơn - nhưng tôi sẽ phân lớp vé từ lớp coupon của bạn - theo cách đó nếu bạn cần phải làm bất cứ munging dữ liệu, bạn có thể đặt mã trong lớp vé của bạn

+0

Phân lớp phụ có nghĩa là mối quan hệ IS-A. Tôi cảm thấy trừ khi nó là đúng trong miền vấn đề, chúng ta không nên làm điều đó trong phần mềm. –

11

trong tập tin coupon.rb:

class Coupon 
    #... 
end 

# add this line of code to make alias for class names 
# option1. if you haven't defined a "Ticket" class: 
Ticket = Coupon 

# option2. if Ticket has been defined, you have to redefine it: 
Object.send :remove_const, "Ticket" 
const_set "Ticket", Coupon 

"Bất cứ liệu tham khảo bắt đầu với một ký tự hoa, trong đó có những cái tên của các lớp học và các module, là một hằng số" - < < Lập trình meta ruby ​​>>, page38, liên tục phần

2

chức năng bạn phải cẩn thận với điều này, bởi vì nếu lớp học của bạn phải trải qua bất kỳ thay đổi trạng thái (thêm , thay đổi hằng số, cla ss biến, vv) nhà nước rằng lớp học của bạn là trong khi bí danh được khởi tạo sẽ không phản ánh những thay đổi được cập nhật trong lớp học của bạn.

Để tránh đường hầm cổ tay mà không bị mất khả năng đọc, bạn có thể lưu trữ lambda trong đối tượng bí danh của mình thay vì lớp thực tế. Tất nhiên, lambda chứa các lớp nhưng điều này đảm bảo bí danh của bạn sẽ gọi lên phiên bản mới nhất của lớp học của bạn.

Tôi đặt mã này vào bộ khởi tạo đường ray supermanpatches.rb (bên trong config/initializers/) & Dagger;

LAP = lambda { LosAngelesParcel } 

Bây giờ bạn có thể gọi đây là sử dụng LAP[] và một phiên bản mới đúc của lớp học của bạn sẽ được nạp. (Cho phép bạn tạo các trường hợp, ví dụ: l = LAP[].new)

& Dagger; chạy một lần khi đường ray được tải & sau đó phổ biến thông qua ứng dụng của bạn, có thể gọi bất kỳ nơi nào giống như biến toàn cục nhưng 'chỉ đọc', vì vậy, hãy nói.

+0

Điều này không chính xác 'lớp A kết thúc; B = A; A.class_eval làm def foo đặt ("test"); kết thúc; B.foo ' Điều này sẽ in thử nghiệm vì cả A và B đều tham chiếu đến cùng một đối tượng trong bộ nhớ. cũng B.object_id bằng A.object_id Vì vậy, bạn không cần phải sử dụng lambda –

+0

Nếu bạn cập nhật các phương pháp của lớp học bạn làm –

+0

Tôi đã cập nhật nó bằng cách sử dụng A.class_eval ở trên, có cách nào khác để cập nhật nó không? –

5

Bất cứ ai đến đây tìm cách bí danh một lớp mô hình đường ray để có một cái tên mới:

tôi đã có thể chỉ đơn giản là làm Foo = Bar, nhưng phải đặt Foo bên trong tập tin mô hình riêng của nó vì vậy mà tôi sẽ không nhận được một lỗi liên tục Uninitialized. ví dụ.

# models/foo.rb 
Foo = Bar 

Ngoài ra bạn có thể tìm weirdness cố gắng sử dụng các bí danh trong các hiệp hội như has_many, has_one, vvTôi đã tìm thấy bạn thường có thể sử dụng không gian tên gốc (hoặc không gian tên thích hợp tùy thuộc vào cách các mô hình của bạn được cấu trúc) để đảm bảo Rails đang cố gắng tự động tải đúng hằng số:

has_many :foo, class_name: '::Foo'