Ghi đè các phương thức thuộc tính ActiveRecord


150

Một ví dụ về những gì tôi đang nói về:

class Person < ActiveRecord::Base
  def name=(name)
    super(name.capitalize)
  end
  def name
    super().downcase  # not sure why you'd do this; this is just an example
  end
end

Điều này có vẻ hiệu quả, nhưng tôi chỉ đọc phần về ghi đè các phương thức thuộc tính trong các tài liệu ActiveRecord :: Base và nó gợi ý sử dụng các phương thức read_attributewrite_attribute. Tôi nghĩ rằng phải có điều gì đó sai với những gì tôi đang làm trong ví dụ trên; mặt khác, tại sao họ lại ban phước cho các phương thức này như là "cách đúng" để ghi đè các phương thức thuộc tính? Họ cũng đang buộc một thành ngữ xấu hơn nhiều, vì vậy phải có một lý do chính đáng ...

Câu hỏi thực sự của tôi: Có điều gì sai với ví dụ này?

Câu trả lời:


211

Báo lại ý kiến ​​của Gareth ... mã của bạn sẽ không hoạt động như được viết. Nó nên được viết lại theo cách này:

def name=(name)
  write_attribute(:name, name.capitalize)
end

def name
  read_attribute(:name).downcase  # No test for nil?
end

Chính xác những gì tôi cần. Cảm ơn Aaron.
bong

18
Điều này không còn đúng nữa. Hoặc siêu hoặc điều này làm việc bây giờ. Tôi đã không kiểm tra ký hiệu băm, tuy nhiên.
heartpunk

2
Trong rails 3, phương thức đọc được chỉ định bởi Aaron hoạt động ở đây, nhưng người viết rằng poster gốc đã chỉ định (cung cấp tên cho siêu) hoạt động tốt và IMHO sạch hơn so với viết thủ công như Aaron gợi ý.
Batkins

1
Tôi đã thử nghiệm phương pháp băm do mipadi đưa ra dưới đây và nó hoạt động như một bùa mê (Rails v 3.2.6)
almathie

Nó không phải là câu trả lời đúng? Cảm ơn @Aaron, cũng đã làm việc cho tôi.
Sadiksha Gautam

94

Là một phần mở rộng cho câu trả lời của Aaron Longwell, bạn cũng có thể sử dụng "ký hiệu băm" để truy cập các thuộc tính đã ghi đè lên bộ truy cập và trình biến đổi:

def name=(name)
  self[:name] = name.capitalize
end

def name
  self[:name].downcase
end

Ký hiệu băm có thể hoạt động, nhưng self.attributethổi ngăn xếp vào ngày 3.2.16.
jrhorn424

Điều này có lợi thế là nó hỗ trợ ||=cho mặc định:def name; self[:name] ||= 'anon'; end
Paul Cantrell

Đối với tôi, ký hiệu băm này hoạt động. Nhưng tôi không biết lý do tại sao nó hoạt động. Ai đó có thể giải thích?
radiantshaw


-1

Tôi có một plugin rails làm cho thuộc tính ghi đè hoạt động với siêu như bạn mong đợi. Bạn có thể tìm thấy nó trên github .

Để cài đặt:

./script/plugin install git://github.com/chriseppstein/has_overrides.git

Để sử dụng:

class Post < ActiveRecord::Base

  has_overrides

  module Overrides
    # put your getter and setter overrides in this module.
    def title=(t)
      super(t.titleize)
    end
  end
end

Khi bạn đã hoàn thành công việc đó:

$ ./script/console 
Loading development environment (Rails 2.3.2)
>> post = Post.new(:title => "a simple title")
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil>
>> post.title = "another simple title"
=> "another simple title"
>> post.title
=> "Another Simple Title"
>> post.update_attributes(:title => "updated title")
=> true
>> post.title
=> "Updated Title"
>> post.update_attribute(:title, "singly updated title")
=> true
>> post.title
=> "Singly Updated Title"
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.