2011-09-05 72 views
12

有沒有辦法在Mongoid中覆蓋模型的setter或getter?喜歡的東西:覆蓋Mongoid模型的setter和getters

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 

其中name方法可以在不使用的虛擬域覆蓋?

+0

相關:http://stackoverflow.com/questions/6699503/mongoid-custom-setters-getters-and-super – marcgg

回答

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

@ user923636您無法更改創建後文檔的「_id」字段。因此,如果項目名稱被更改,您將不得不刪除舊文檔並使用更改後的名稱創建一個新文檔。 – rubish

23

更好地利用

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

方法

self[:name] = projectname.capitalize 

可能是危險的,原因與它超載會導致無限遞歸

+1

謝謝我得到了自我[:名字]的遞歸。超級作品 – GTDev

+0

@GearHead我已經切換到超級時間(它看起來更好),儘管仍然有部分代碼使用self [:name]表示法,直到現在還沒有面臨任何遞歸。 – rubish

+2

如果沒有超級課堂,「超級」如何運作? 'Mongoid :: Document'包含在Module中,我在這裏很困惑...... – tothemario

1

我有一個類似的問題與需要覆蓋「belongs_to:user」關係的「用戶」設置者。我不僅爲這種情況提出了這個解決方案,而且還包裝了在同一個類中已經定義的任何方法。

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 

這可以讓你做你的模型類以下內容:

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

正是我在找什麼,和很好的解決方案。 +1 – user2398029

+0

不要嘗試重新發明自行車。爲此使用alias_method_chain。 – sandrew

+0

感謝您的支持!在關係制定者和獲得者方面也有問題。 sandrew的評論讓我看看a_m_c,並且我學習了Ruby 2.0的Module#prepend。偉大的解決方案,真正乾淨 - http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html –