[rubin 1.8]
Załóżmy, że mam:
dummy "string" do
puts "thing"
end
Teraz jest to wywołanie metody, która ma jako argumenty wejściowe jeden ciąg i jeden blok. Miły.
Załóżmy teraz, że mogę mieć wiele podobnych wywołań (różne nazwy metod, te same argumenty). Przykład:
otherdummy "string" do
puts "thing"
end
Teraz, ponieważ robią to samo, a mogą być setki, nie chcę tworzyć metody instancji dla każdego z nich w poszukiwanej klasie. Wolałbym znaleźć sprytny sposób na dynamiczne definiowanie metody w czasie wykonywania w oparciu o ogólną zasadę.
Czy to jest możliwe? Jakie techniki są powszechnie stosowane?
Dzięki
3 odpowiedzi
Szczególnie lubię używać method_missing
, zwłaszcza gdy kod, którego chcesz użyć, jest bardzo podobny w różnych wywołaniach metod. Oto przykład z tej strony - za każdym razem, gdy ktoś wywoła x.boo
i boo
nie istnieje, method_missing jest wywoływana z boo
, argumentami do boo
i (opcjonalnie) blokiem:
class ActiveRecord::Base
def method_missing(meth, *args, &block)
if meth.to_s =~ /^find_by_(.+)$/
run_find_by_method($1, *args, &block)
else
super # You *must* call super if you don't handle the
# method, otherwise you'll mess up Ruby's method
# lookup.
end
end
def run_find_by_method(attrs, *args, &block)
# Make an array of attribute names
attrs = attrs.split('_and_')
# #transpose will zip the two arrays together like so:
# [[:a, :b, :c], [1, 2, 3]].transpose
# # => [[:a, 1], [:b, 2], [:c, 3]]
attrs_with_args = [attrs, args].transpose
# Hash[] will take the passed associative array and turn it
# into a hash like so:
# Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 }
conditions = Hash[attrs_with_args]
# #where and #all are new AREL goodness that will find all
# records matching our conditions
where(conditions).all
end
end
define_method
również wygląda na to, że będzie działać w Twoim przypadku, ale mam z tym mniej doświadczenia niż method_missing
. Oto przykład z tego samego linku:
%w(user email food).each do |meth|
define_method(meth) { @data[meth.to_sym] }
end
Tak, jest kilka opcji.
Pierwszy to method_missing
. Jej pierwszym argumentem jest symbol będący wywołaną metodą, a pozostałe argumenty to argumenty, które zostały użyte.
class MyClass
def method_missing(meth, *args, &block)
# handle the method dispatch as you want;
# call super if you cannot resolve it
end
end
Inną opcją jest dynamiczne tworzenie metod instancji w czasie wykonywania, jeśli wiesz z góry, które metody będą potrzebne. Należy to zrobić w klasie, a jeden przykład jest taki:
class MyClass
1.upto(1000) do |n|
define_method :"method_#{n}" do
puts "I am method #{n}!"
end
end
end
Powszechnym wzorcem jest wywoływanie define_method
w metodzie klasy, która musi utworzyć nowe metody instancji w czasie wykonywania.
puts "I am method #{n}!"
. W każdym razie dobra odpowiedź!
Użyj metody define_:
class Bar
end
bar_obj = Bar.new
class << bar_obj
define_method :new_dynamic_method do
puts "content goes here"
end
end
bar_obj.new_dynamic_method
Wynik:
content goes here
Podobne pytania
Powiązane pytania
Nowe pytania
ruby
Ruby to wieloplatformowy, dynamiczny, zorientowany obiektowo język interpretowany typu open source. Znacznik [ruby] jest przeznaczony do pytań związanych z językiem Ruby, w tym jego składnią i bibliotekami. Pytania dotyczące Ruby on Rails powinny być oznaczone tagiem [ruby-on-rails].
method_missing
będącymi metodami, których nie znamy a priori.