2011-09-05 11 views
12

Czy istnieje sposób na przesłonięcie setera lub gettera dla modelu w Mongoid? Coś takiego:Zastępowanie ustawiających i pobierających modelu Mongoid'a

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 

gdzie metoda name może zostać nadpisana bez użycia wirtualnych pól?

+0

związane: http://stackoverflow.com/questions/6699503/mongoid-custom-setters-getters-and-super – marcgg

Odpowiedz

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

@ user923636 nie można zmienić pola "_id" dokumentu po utworzeniu. Więc jeśli nazwa projektu zostanie zmieniona, będziesz musiał usunąć stary dokument i utworzyć nowy ze zmienioną nazwą. – rubish

23

lepsze wykorzystanie

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

metoda

self[:name] = projectname.capitalize 

może być niebezpieczne, bo przeciążenie z nim może spowodować Kompletne rekursji

+1

dzięki Mam rekursję od siebie [: nazwa]. super works – GTDev

+0

@GearHead Zmieniłem także tryb super na timme (wygląda to lepiej), chociaż części mojego kodu wciąż używają notacji self [: name] i nie mają do tej pory żadnych rekurencji. – rubish

+2

W jaki sposób "super" może działać, jeśli nie ma superklasy? 'Mongoid :: Dokument' jest dołączony jako moduł, jestem zdezorientowany tutaj ... – tothemario

1

Miałem podobny problem z konieczności zastąpić seter "user" dla relacji belongs_to: user. Wymyśliłem to rozwiązanie nie tylko w tym przypadku, ale także w celu zawijania dowolnej metody już zdefiniowanej w tej samej klasie.

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 

ta pozwala na wykonywanie następujących czynności w swojej klasie modelu:

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

Dokładnie to, czego szukałem i dobre rozwiązanie. +1 – user2398029

+0

Nie próbuj odkrywać roweru na nowo. W tym celu użyj alias_method_chain. – sandrew

+0

dzięki za to! Problem z ustawieniami relacji i pobierającymi. Komentarz Sandrew pozwolił mi zajrzeć do a_m_c i dowiedziałem się o module # Ruby 2.0. Świetne rozwiązanie i naprawdę czyste - http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html –

Powiązane problemy