Làm cách nào tôi có thể ghi đè phương thức getter trong mô hình ActiveRecord?


98

Tôi đang cố gắng ghi đè một phương thức getter cho một mô hình ActiveRecord. Tôi có một thuộc tính được gọi nametrong mô hình Categoryvà tôi muốn có thể làm điều gì đó như sau:

def name
  name_trans || name
end

Nếu name_transthuộc tính không phải là nil, thì trả về nó, nếu không thì trả về namethuộc tính. Tôi sẽ làm điều này như thế nào?

Điều này sau đó sẽ được gọi là bình thường như sau:

@category.name

Câu trả lời:


123

Các Rails Style Guide khuyến cáo sử dụng self[:attr]qua read_attribute(:attr).

Bạn có thể sử dụng nó như thế này:

def name
  name_trans || self[:name]
end

Tại sao nó tốt hơn? Đừng chỉ liên kết đến một trang web khác, hãy bao gồm các thông tin liên quan ở đây. Các liên kết có thể trở nên không hợp lệ
JamesT

2
Để biết thêm một chút ngữ cảnh, hãy xem tại đây: github.com/bbatsov/rails-style-guide/issues/155
mimsugara vào

98

Cập nhật: Phương pháp ưa thích theo Hướng dẫn Kiểu Rails là sử dụng self[:name]thay cho read_attributewrite_attribute. Tôi khuyến khích bạn bỏ qua câu trả lời của tôi và thay vào đó thích câu trả lời này hơn .


Bạn có thể thực hiện chính xác như vậy, ngoại trừ việc bạn cần sử dụng read_attributeđể thực sự tìm nạp giá trị của thuộc tính name và tránh lệnh gọi đệ quy đến namephương thức:

def name 
  name_trans || read_attribute(:name)
end

2
Bất kỳ ý tưởng tại sao Rubocop thích self[:name]hơn read_attribute[:name]?
Zack Xu

18

Tôi muốn thêm một tùy chọn khác để ghi đè phương thức getter, đơn giản là super.

def name
  name_trans || super
end

điều này không chỉ hoạt động trên phương thức getter thuộc tính mà còn cả phương thức getter liên kết nữa , quá。


1
Đây là những gì Rails dẫn hiện giới thiệu, cho getter và setter: api.rubyonrails.org/classes/ActiveRecord/...
sandre89

5

Ghi đè getter và sử dụng read_attributekhông hoạt động cho các liên kết, nhưng bạn có thể sử dụng alias_method_chainthay thế.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Bạn có thể đưa ra một ví dụ thích hợp ...?
Arup Rakshit

Tốt. Tôi vừa nhìn thấy doco . Bây giờ nếu tôi gọi nameđối tượng mô hình, đối tượng nào sẽ được gọi - name_with_overridehoặc name_without_override?
Arup Rakshit

1
namebây giờ sẽ gọi name_with_override. Nếu bạn muốn gọi phương thức gốc vì lý do nào đó, bạn có thể gọi name_without_override.
Patrick Oscity

OI see .. Cảm ơn vì câu trả lời của bạn //
Arup Rakshit

2

Nếu bạn sử dụng các thuộc tính cửa hàng như thế này

store :settings, accessors: [:volume_adjustment] 

hoặc sử dụng đá quý như hstore_accessor liên kết đá quý

Vì vậy, bạn đã kết thúc bằng cách sử dụng storephương thức trên mô hình, sau đó để ghi đè phương thức bạn không thể sử dụng self.read_attribute, bạn phải sử dụng thay superthế như vậy:

def partner_percentage
  super.to_i || 10
end

0

Nếu ai đó muốn cập nhật giá trị sau name_transtrong phương thức getter, bạn có thể sử dụng self [: name] =.

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

0

Bạn có thể sử dụng phương thức read_attribute của Rails. Tài liệu về đường ray


mặc dù liên kết này có thể trả lời câu hỏi, nhưng câu trả lời chỉ liên kết không được phép trên SO, vui lòng thêm một số ngữ cảnh vào câu trả lời của bạn từ những gì đằng sau liên kết đó. Cảm ơn! :)
AJT82
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.