22. Hack1.rb (part 1)
class MyObj
alias_method :hello_original,
:hello
end
:hello_original
method body
A
:hello
23. Hack1.rb (part 2)
class MyObj
def hello_with_bracket(s)
“{” + hello_original(s) + ”}”
end
end
method body
B
:hello_with_bracket
send message
:hello_original
24. Hack1.rb (part 3)
class MyObj
alias_method :hello,
:hello_with_bracket
end
method body
B
method body
A
:hello_with_bracket
:hello
29. Hack2.rb (yes, that’s all)
class MyObj
m = instance_method(:hello)
define_method(:hello) do |s|
“{” + m.bind(self).call(s) + “}”
end
end
30. Hack2.rb
class MyObj
m = instance_method(:hello)
define_method(:hello) do |s|
“{” + m.bind(self).call(s) + “}”
end
end
m (a local var)
method body
A
:hello
31. Hack2.rb
class MyObj
m = instance_method(:hello)
define_method(:hello) do |s|
“{” + m.bind(self).call(s) + “}”
end
end
method body
B
method body
A
:hello
32. Hack2.rb (Ah, ha!)
class MyObj
m = instance_method(:hello)
define_method(:hello) do |s|
“{” + m.bind(self).call(s) + “}”
end
end
method body
B
call directly
method body
A
:hello
35. Example (Safer)
def send_money(from, to, amount)
ActiveRecord::Base.transcation do
from.balance -= amount
to.balance += amount
from.save!
to.save!
end
end
36. Example in Ruby
def send_money(from, to, amount)
ActiveRecord::Base.transcation do
# do operations
end
end
37. Example in Python
def send_money(from, to, amount):
try:
db.start_transcation()
# do operations
db.commit_transcation()
except:
db.rollback_transcation()
raise
38. Decorating in Python
Form 1:
@transcational
def send_money(from, to, amount):
# do operations
Form 2:
def send_money(from, to, amount):
# do operations
send_money = transcational(send_money)
40. Decorating in Ruby
class Bank
extend Transcational # include decorator
def send_money(from, to, amount)
# do operations
end
transcational :send_money # decorate!
end
41. Decorator in Ruby
module Transcational
def transcational(mthd_name)
mthd = instance_method(mthd_name)
define_method(mthd_name) do |*args, &blk|
ActiveRecord::Base.transcation {
# call decoratee
mthd.bind(self).call(*args, &blk)
}
end
end
end
51. Inside Refinement
Actually, refinement creates an annoymous
module to mixin a class.
module MyLib
refine String do
puts self.is_a?(Module) # => true
puts self
# => #<refinement:String@MyLibrary>
end
end
56. using is lexical
1. Refinements are activated only at top-level
- Not inside class, module, and method scope
2. Scope of the effect is the whole source code
57. using is lexical
Please DO NOT…
class Foo
using MyLib
end
module Moo
using MyLib
end
def bar
using MyLib
end
58. using is lexical
# refinement of MyLib is deactived
# “World”.hello # => NoMethodError
using MyLib # activate!
# refinement of MyLib is activated
def hello_world
“World”.hello
end
# END OF FILE
Scope of
MyLib
Refinement
59. Refinement in Ruby
1. Actually, it is based on Mixining
2. Avoid global scope corruption
3. Prefer lexical scope to runtime scope
=> easy to use, just like import in Java