2011-09-05 21 views
12

Có cách nào để ghi đè lên một bộ setter hoặc getter cho một mô hình trong Mongoid không? Một cái gì đó như:Ghi đè lên các bộ định vị và hình dáng của mô hình Mongoid

class Project 
    include Mongoid::Document 
    field :name, :type => String 
    field :num_users, type: Integer, default: 0 
    key :name 
    has_and_belongs_to_many :users, class_name: "User", inverse_of: :projects 

    # This will not work 
    def name=(projectname) 
    @name = projectname.capitalize 
    end 
end 

phương pháp name có thể được ghi đè mà không sử dụng các trường ảo?

+0

liên quan: http://stackoverflow.com/questions/6699503/mongoid-custom-setters-getters-and-super – marcgg

Trả lời

16
def name=(projectname) 
    self[:name] = projectname.capitalize 
end 
+1

@ user923636 bạn không thể thay đổi trường "_id" của tài liệu khi được tạo. Vì vậy, nếu tên dự án được thay đổi, bạn sẽ phải xóa tài liệu cũ và tạo một tài liệu mới với tên đã thay đổi. – rubish

23

tốt hơn sử dụng

def name=(projectname) 
    super(projectname.capitalize) 
end 

phương pháp

self[:name] = projectname.capitalize 

có thể nguy hiểm, nguyên nhân quá tải với nó có thể gây ra đệ quy vô tận

+1

cảm ơn tôi đã nhận được đệ quy từ chính [: tên]. super works – GTDev

+0

@GearHead Tôi cũng đã chuyển sang super over timme (có vẻ tốt hơn), mặc dù các phần còn lại của mã của tôi sử dụng ký tự [: name] và không phải đối mặt với bất kỳ cuộc truy tìm nào cho đến bây giờ. – rubish

+2

Làm thế nào để 'super' có thể hoạt động nếu không có siêu hạng? 'Mongoid :: Tài liệu' được bao gồm trong Mô-đun, tôi bị nhầm lẫn ở đây ... – tothemario

1

Tôi đã có một vấn đề tương tự với cần phải ghi đè bộ chọn "người dùng" cho mối quan hệ thuộc_to: user. Tôi đã đưa ra giải pháp này cho không chỉ trường hợp này, nhưng cho gói bất kỳ phương pháp đã được xác định trong cùng một lớp học.

class Class 
    def wrap_method(name, &block) 
    existing = self.instance_method(name) 

    define_method name do |*args| 
     instance_exec(*args, existing ? existing.bind(self) : nil, &block) 
    end 
end 

này cho phép bạn làm như sau trong lớp mô hình của bạn:

wrap_method :user= do |value, wrapped| 
    wrapped.call(value) 
    #additional logic here 
end 
+0

Chính xác những gì tôi đang tìm kiếm và giải pháp tốt đẹp. +1 – user2398029

+0

Đừng cố gắng tái tạo lại chiếc xe đạp. Sử dụng alias_method_chain cho việc này. – sandrew

+0

cảm ơn vì điều này! Gặp rắc rối với người định cư mối quan hệ và getters là tốt. bình luận của sandrew đã cho tôi nhìn vào a_m_c's và tôi đã học về phần mở rộng Module # của Ruby 2.0. Giải pháp tuyệt vời và thực sự sạch sẽ - http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html –

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