Johnathan, Nie jestem pewien, jeśli nadal zastanawiasz się o to, ale istnieją dwa różne sposoby korzystania z modułów w Ruby. A.) używasz modułów w ich samodzielnej formie Base :: Tree.entity (params) bezpośrednio w kodzie lub B.) używasz modułów jako mixin lub metod pomocniczych.
A. Umożliwi wykorzystanie modułów jako wzorca przestrzeni nazw. To jest dobre dla dużych projektów, w których jest szansa dla nazwy metody konflikty
module Base
module Tree
def self.entity(params={},&block)
# some great code goes here
end
end
end
Teraz można to wykorzystać, aby stworzyć jakąś strukturę drzewa w kodzie, bez konieczności wystąpienia nową klasę dla każdego połączenia do bazy :: Tree.entity.
Innym sposobem wykonywania przestrzeni nazw jest podział na klasy.
module Session
module Live
class Actor
attr_accessor :type, :uuid, :name, :status
def initialize(params={},&block)
# check params, insert init values for vars..etc
# save your callback as a class variable, and use it sometime later
@block = block
end
def hit_rock_bottom
end
def has_hit_rock_bottom?
end
...
end
end
class Actor
attr_accessor :id,:scope,:callback
def initialize(params={},&block)
self.callback = block if block_given?
end
def respond
if self.callback.is_a? Proc
# do some real crazy things...
end
end
end
end
Teraz mamy potencjał nakładania się w naszych klasach. Chcemy wiedzieć, że kiedy tworzymy klasę aktorów, że jest to właściwa klasa, to właśnie tutaj przydatne są przestrzenie nazw.
Session::Live::Actor.new(params) do |res|...
Session::Actor.new(params)
B. Mix-Ins To są twoi przyjaciele. Używaj ich, gdy myślisz, że będziesz musiał zrobić coś więcej niż jeden raz w swoim kodzie.
module Friendly
module Formatter
def to_hash(xmlstring)
#parsing methods
return hash
end
def remove_trailing_whitespace(string,&block)
# remove trailing white space from that idiot who pasted from textmate
end
end
end
Teraz, kiedy trzeba formatować xmlstring jako hash lub usunąć końcowe spacje w którymkolwiek z przyszłych kodu, po prostu zmieszać go w.
module Fun
class Ruby
include Friendly::Formatter
attr_accessor :string
def initialize(params={})
end
end
end
Teraz można sformatować ciąg w swojej klasa.
fun_ruby = Fun::Ruby.new(params)
fun_ruby.string = "<xml><why><do>most</do><people></people><use>this</use><it>sucks</it></why></xml>"
fun_ruby_hash = fun_ruby.to_hash(fun_ruby.string)
Mam nadzieję, że jest to wystarczająco dobre wytłumaczenie.Powyższe punkty są dobrym przykładem sposobów rozszerzania klas, ale w przypadku modułów najtrudniejsze jest zastosowanie słowa kluczowego self. Odnosi się do zakresu obiektu w hierarchii obiektu ruby. Jeśli więc chcesz użyć modułu jako miksu i nie chcesz deklarować niczego pojedynczego, nie używaj własnego słowa kluczowego, ale jeśli chcesz zachować stan w obiekcie, po prostu użyj klasy i wymieszaj- w modułach, które chcesz.
Czy możesz podać konkretny przypadek, w którym chciałbyś to zrobić? Dziedziczenie modułów jest tym, czego naprawdę chcesz, a to jest specjalnie i celowo obsługiwane tylko dla klas w Ruby. Dlaczego nie: a) zawsze uwzględniać B i A w tym samym obiekcie, lub b) gdy B zawiera również A? – Phrogz
Powód, dla którego chcę to, jest trochę skomplikowany. Ten moduł służy do tworzenia wielu klas ActiveRecord :: Base z dokumentu XML opisującego tabele i relacje DB. Chcę móc to zrobić kilka razy. Kod modułu jest taki sam dla każdego, ale aby przestrzenie nazw i powiązane klasy nie kolidowały, muszą być odrębnymi modułami. Nie chcę też tworzyć instancji klasy, aby włączyć moduł za każdym razem, gdy to robię, wykluczając i stosując metody instancji. –