Article View: pl.comp.lang.ruby
Article #187Re: Ruby i dekorator
From: Jaroslaw Zabiello
Date: Thu, 07 Sep 2006 16:35
Date: Thu, 07 Sep 2006 16:35
139 lines
4798 bytes
4798 bytes
Dnia Thu, 07 Sep 2006 14:59:22 +0200, Marcin Mielżyński napisał(a):
>> method_added() wyłapuje fakt dodania metody, więc po co mi to? alias nie
>> potrzebuję, bo chcę zachować tą samą nazwę. A define_method tworzy a nie
>> odczytuje ciało metody.
>
> method_added będzie bardzo przydatne dla zbliżenia do pythonowej wersji,
> method_alias i define_method - koniecznie - no chyba chyba że przez
> undef_method.
>
> podstawy w bardzo prosty sposób można zrobić tak (dwie wersje):
>
> class Class
>
> def around meth,pre,post
> alias_method :"old_#{meth}",meth.to_sym
> define_method meth do
> pre.call
> send :"old_#{meth}"
> post.call
> end
> end
>
> def around2 meth
> alias_method :"old_#{meth}",meth.to_sym
> define_method meth do
> yield method(:"old_#{meth}").to_proc
> end
> end
>
> end
>
> class A
> def meth
> p "meth"
> end
>
> def meth2
> p "meth2"
> end
> end
>
> A.around :meth, proc{p "pre"},proc{p "post"}
> A.new.meth
>
> A.around2 :meth2 do |m|
> p "pre2"
> m.call
> p "post2"
> end
>
> A.new.meth2
>
>
> łatwo przerobić na dużo wygodniejsze użycie...
Pogubiłem się trochę w tym kodzie. Chodzi mi o odpowiednik w Ruby czegoś
takiego jak tu w Pythonie:
>>> headers = {'Content-Type': 'text/html'}
>>> class Base:
... @classmethod
... def hello(cls, msg):
... headers['Content-Type'] = 'application/xml'
... return msg
...
>>> Base.hello('JA')
'JA'
>>> headers
{'Content-Type': 'application/xml'}
>>>
Jak widać metoda hello() zmieniła słownik headers. Moim celem jest tak
zmienić klasę Base aby tego NIE zrobiła. Np. tak:
>>> headers = {'Content-Type': 'text/html'}
>>> x = Base.hello
>>> class Base:
... @classmethod
... def hello(cls, msg):
... old = headers['Content-Type']
... result = x(msg)
... if old != headers['Content-Type']:
... headers['Content-Type'] = old
... return result
...
>>> Base.hello('JA')
'JA'
>>> headers
{'Content-Type': 'text/html'}
W Pythonie wyssałem cała metodę za pomocą prostego przypisania. Następnie
otworzyłem tą klasę, dodałem warunki chroniące i wywołałem z powrotem. W
tym ujęciu nie jest w ogóle ważne co sie dzieje w metodzie hello(). Z mego
pkt. widzenia może być "czarną skrzynką". Wiem tylko tyle, że modyfikowała
mi jeden klucz w zewn. słownik i przed tym chciałem się zabezpieczyć.
Wracając do Rubiego i do konretnego problemu jaki spotkałem w RoR. Chcę
poprawić metodę render_to_string() bo ona gdzieś modyfikuje nagłówek HTTP.
Pierwotnie definicja wygląda tak:
module ActionController
class Base
def render_to_string(options = nil, &block)
result = render(options, &block)
erase_render_results
forget_variables_added_to_assigns
reset_variables_added_to_assigns
result
end
end
end
Nie interesuje mnie co sie dzieje w środku. Chcę tylko dodać zabezpieczenie
przed zmianą klucza Content-Type w @headers. Zrobiłem to trochę siłowo,
kopiując wszystko jak leci i dodając swój warunek:
module ActionController
class Base
def render_to_string(options = nil, &block)
content_type = @headers['Content-Type']
result = render(options, &block)
erase_render_results
forget_variables_added_to_assigns
reset_variables_added_to_assigns
if content_type != @headers['Content-Type']
@headers['Content-Type'] = content_type
end
result
end
end
end
Interesowało mnie jednak, czy mógłbym to zrobić bardziej elegancko, bez
kopiowania środka metody. Tak jak w Pythonie.
--
Jarosław Zabiełło
http://blog.zabiello.com
Technical Details
Message-ID:
<1x2rocd4cjsfx.1pa1f7xfso7pe.dlg@40tude.net>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!not-for-mailReferences:
<re7vnvdwaxef.1xsf47isecttl$.dlg@40tude.net> <edp0jp$ph2$1@news.onet.pl> <1b5oye9z0x1aq.n67fdxozbl7i.dlg@40tude.net> <edp53n$b6v$1@news.onet.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!not-for-mail From: Jaroslaw Zabiello <hipertracker@gmail.com> Newsgroups: pl.comp.lang.ruby Subject: Re: Ruby i dekorator Date: Thu, 7 Sep 2006 17:35:49 +0100 Organization: "Portal Gazeta.pl -> http://www.gazeta.pl" Lines: 139 Message-ID: <1x2rocd4cjsfx.1pa1f7xfso7pe.dlg@40tude.net> References: <re7vnvdwaxef.1xsf47isecttl$.dlg@40tude.net> <edp0jp$ph2$1@news.onet.pl> <1b5oye9z0x1aq.n67fdxozbl7i.dlg@40tude.net> <edp53n$b6v$1@news.onet.pl> NNTP-Posting-Host: 82.195.148.233 Mime-Version: 1.0 X-Trace: inews.gazeta.pl 1157646954 7769 82.195.148.233 (7 Sep 2006 16:35:54 GMT) X-Complaints-To: usenet@agora.pl NNTP-Posting-Date: Thu, 7 Sep 2006 16:35:54 +0000 (UTC) X-User: newsgate2006 User-Agent: 40tude_Dialog/2.0.15.1pl Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit