2008-10-09 28 views
91

Tôi thực sự không thể tìm thấy điều này trong tài liệu Rails nhưng nó có vẻ như 'mattr_accessor'Mô-đun hệ luỵ cho 'attr_accessor' (getter & setter) trong một bình thường của Ruby lớp.Mattr_accessor trong mô-đun Rails là gì?

Ví dụ: trong một lớp học

class User 
    attr_accessor :name 

    def set_fullname 
    @name = "#{self.first_name} #{self.last_name}" 
    end 
end 

Ví dụ: trong một module

module Authentication 
    mattr_accessor :current_user 

    def login 
    @current_user = session[:user_id] || nil 
    end 
end 

phương pháp helper này được cung cấp bởi ActiveSupport.

Trả lời

159

Đường ray mở rộng Ruby với cả hai mattr_accessor (Trình truy cập mô-đun) và cattr_accessor (cũng như _ reader/_writer phiên bản). Như Ruby attr_accessor tạo ra phương pháp getter/setter cho trường, cattr/mattr_accessor cung cấp phương thức getter/setter tại lớp hoặc mô-đun cấp. Như vậy:

module Config 
    mattr_accessor :hostname 
    mattr_accessor :admin_email 
end 

là viết tắt của:

module Config 
    def self.hostname 
    @hostname 
    end 
    def self.hostname=(hostname) 
    @hostname = hostname 
    end 
    def self.admin_email 
    @admin_email 
    end 
    def self.admin_email=(admin_email) 
    @admin_email = admin_email 
    end 
end 

Cả hai phiên bản cho phép bạn truy cập vào các biến mô-đun cấp như vậy:

>> Config.hostname = "example.com" 
>> Config.admin_email = "[email protected]" 
>> Config.hostname # => "example.com" 
>> Config.admin_email # => "[email protected]" 
+0

Trong ví dụ của bạn, bạn giải thích rằng 'mattr_accessor' sẽ là viết tắt của các biến lớp dụ (' @ variable's), nhưng mã nguồn dường như tiết lộ họ thực sự thiết lập/đọc các biến lớp. Bạn có thể giải thích sự khác biệt này không? – sandre89

35

Here's the source for cattr_accessor

Here's the source for mattr_accessor

Như bạn có thể thấy, chúng khá giống nhau.

Tại sao có hai phiên bản khác nhau? Đôi khi bạn muốn viết cattr_accessor trong một mô-đun, vì vậy bạn có thể sử dụng nó cho thông tin cấu hình like Avdi mentions.
Tuy nhiên, cattr_accessor không hoạt động trong mô-đun, vì vậy, chúng cũng ít nhiều đã sao chép mã để hoạt động cho các mô-đun. Ngoài ra, đôi khi bạn có thể muốn viết một phương thức lớp trong một mô-đun, như vậy bất cứ khi nào bất kỳ lớp nào bao gồm mô-đun, nó sẽ nhận được phương thức lớp đó cũng như tất cả các phương thức thể hiện. mattr_accessor cũng cho phép bạn thực hiện việc này.

Tuy nhiên, trong trường hợp thứ hai, hành vi của nó khá lạ. Quan sát đoạn mã sau, đặc biệt lưu ý các @@mattr_in_module bit

module MyModule 
    mattr_accessor :mattr_in_module 
end 

class MyClass 
    include MyModule 
    def self.get_mattr; @@mattr_in_module; end # directly access the class variable 
end 

MyModule.mattr_in_module = 'foo' # set it on the module 
=> "foo" 

MyClass.get_mattr # get it out of the class 
=> "foo" 

class SecondClass 
    include MyModule 
    def self.get_mattr; @@mattr_in_module; end # again directly access the class variable in a different class 
end 

SecondClass.get_mattr # get it out of the OTHER class 
=> "foo" 
+0

Đây là một bản ghi nhớ mà tôi khá khó khăn khi thiết lập default_url_options trực tiếp (một mattr_accessor). Một khi lớp học sẽ đặt chúng theo cách này và cách khác sẽ đặt chúng theo một cách khác, do đó tạo ra các liên kết không hợp lệ. –

+0

Trong phiên bản mới nhất của Rails 'cattr_ *' bây giờ là bí danh cho 'mattr_ *'. Xem ['cattr_accessor' source] (https://github.com/rails/rails/blob/4-2-stable/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb) – ouranos

Các vấn đề liên quan