Slide 1

Slide 1 text

R b E i i n

Slide 2

Slide 2 text

D e P i o o h e h n e R b

Slide 3

Slide 3 text

h t ://w w. i k .c m/p o o /j h _l m/1 1 9 8 1 / M t , w s m c t i e u e P o r m i r p a h a s? M t , E n e n o R b 8

Slide 4

Slide 4 text

h t ://i c.c n e s t o s e w r .o g/s o s/d t i 1 3 .h m ★ “I h l s h m n t o g t ." ★ “I h l s o t i k b t e ." ★ “I m k s o a b t e p o r m e ."

Slide 5

Slide 5 text

★ “R b m k s p o r m e s h p y.” ★ “I w n e o m n m z y f u t a i n d r n p o r m i g.” ★ “D n't u d r s i a e h h m n f c o .” h t ://w w.a t m .c m/i t /r b .h m

Slide 6

Slide 6 text

★ E t o f n für P o u t v tät n S aß ★ P i z p e o I t r c i n D s g ★ “P i c p e f l a t a t n s m n " – V r i r n e f h e e E t i k e m n m e e W k p d a, h t ://e .w k p d a.o g/w k /R b _(p o r m i g_l n u g )#P i o o h

Slide 7

Slide 7 text

W s n l c e K n e t

Slide 8

Slide 8 text

A l s i t e n O j k

Slide 9

Slide 9 text

(F s ) a l s i t e n M t o e

Slide 10

Slide 10 text

F n F c ™ 23.method(:-).class # Method M t o e s n O j k e 8

Slide 11

Slide 11 text

O e C a s

Slide 12

Slide 12 text

C o u e

Slide 13

Slide 13 text

D c T p n

Slide 14

Slide 14 text

D n m c R n i e

Slide 15

Slide 15 text

I 's a k n o M g c - B i p e e -

Slide 16

Slide 16 text

D m i S e i c L n u g

Slide 17

Slide 17 text

get "/:name" do "Hello #{params["name"]}!" end

Slide 18

Slide 18 text

class Customer < ActiveRecord::Base has_many :orders, dependent: :destroy validates_presence_of :name end

Slide 19

Slide 19 text

describe Account do it "has a balance of zero when first created" do expect(Account.new.balance).to eq(0) end end

Slide 20

Slide 20 text

Application.configure do client_timeout 2.minutes buffer_size 500.kilobytes end

Slide 21

Slide 21 text

B u a t n für D L ★ C d B o k & C o u e ★ B öc e n v r c i d n n K n e t n a s üh e ★ F n t o a i ät n e S r c e e w i e n ★ M t p o r m i r n : d n m s h C d g n r e u g, method_missing C l b c s

Slide 22

Slide 22 text

Application.configure do client_timeout 2.minutes buffer_size 500.kilobytes end class Application def self.configure(&block) new.instance_eval(&block) end def method_missing(method, *args) @config[method] = args.first end end 8

Slide 23

Slide 23 text

def method_missing(method, *args) if args.present? @config[method] = args.first else return @config[method] end end

Slide 24

Slide 24 text

["client_timeout", "buffer_size"].each do |method| define_method method do |value| @config[method] = value end end

Slide 25

Slide 25 text

D c r t r

Slide 26

Slide 26 text

class DBLayer decorate CacheDecorator def find(id) # … end end

Slide 27

Slide 27 text

class CacheDecorator < BaseDecorator def call(*args) # … before method result = @closure.call(*args) # … after method return result end end

Slide 28

Slide 28 text

???

Slide 29

Slide 29 text

★ Z d k r e e d M t o e n e ★ M t o e e t a i r n ★ D c r t r i e M t o e i i i l s e e ★ P o y M t o e d n e e

Slide 30

Slide 30 text

# Detect the method for decoration def method_added(name) if decorator_class = @decorate_next_with @decorate_next_with = nil DecoratorHelper.apply_decorator(decorator_class, name, self) end end

Slide 31

Slide 31 text

# Extract the original method decorated_method = target.instance_method(method_name) target.send(:remove_method, method_name) # Initialize decorator with original method target.decorators[method_name] = { decorator: decorator.new, method: decorated_method }

Slide 32

Slide 32 text

# Define the proxy method new_method = <<-RUBY def #{method_name}(*params, &block) @_#{method_name}_decorator.call(*params, &block) end RUBY # Add the proxy method to the original class target.class_eval new_method

Slide 33

Slide 33 text

C l b c s

Slide 34

Slide 34 text

Events.subscribe :create_user # [EVENT] The service 'create_user' was called with {:name=>"Rainbow Dash", :email=>"[email protected]"} # [CreateUserService] Creating the user 'Rainbow Dash' CreateUserService.execute(name: "Rainbow Dash", email: "[email protected]")

Slide 35

Slide 35 text

class CreateUserService def self.execute(name: "", email: "") puts "[CreateUserService] Creating the user '#{name}'" end end

Slide 36

Slide 36 text

???

Slide 37

Slide 37 text

★ A f r e u g: K i e S p r-K a s , e n M d l i k u i r n ★ D n m s h S r i e-K a s n n e ★ execute-M t o e e w i e n

Slide 38

Slide 38 text

inherited(subclass) method_added(method_name)

Slide 39

Slide 39 text

class Object def self.inherited(subclass) return nil unless subclass.to_s.end_with? "Service" subclass.instance_eval do # ... end end end N r S r i e-K a s n e w i e n 8

Slide 40

Slide 40 text

subclass.instance_eval do def self.singleton_method_added(method_name) return nil unless method_name == :execute class << self # ... end end end CreateUserService.execute i t e n K a s n e h d 8 8 8 8 ? ? ? ? ? ? ?

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

S n l t n C a s ★ J d s O j k a s i e e g n e a K a s , d r u h S n l t n C a s ★ I s a z-V r a l n (Z s a d) e t n O j k e /I s a z n ★ M t o e (V r a t n) l b n n K a s n/M d l n ★ D h r u s s für j d s O j k i e e g n K a s g b n!

Slide 43

Slide 43 text

C a s s, S n l t n C a s s, O j c s....?! C a s C e t U e S r i e # s p r l s c a s s n l t n c a s

Slide 44

Slide 44 text

M t o e n e i R b C e t U e S r i e O j c # #> #

Slide 45

Slide 45 text

subclass.instance_eval do def self.singleton_method_added(method_name) return nil unless method_name == :execute class << self # ... end end end

Slide 46

Slide 46 text

class << self alias_method :execute_without_event_trigger, :execute undef_method :execute def execute_with_event_trigger(*args) Events.publish … execute_without_event_trigger(*args) end def method_missing(meth, *args, &blk) if meth.to_sym == :execute execute_with_event_trigger(*args) else super end end end A t M t o e e t e n n… 8 …u d n u "h n u üg n" 8

Slide 47

Slide 47 text

F n F c undef_method(symbol) → self P e e t h c r e t c a s r m r s o d n o c l s o t e n m d m t o . C n r s h s i h remove_method, w i h d l t s h m t o r m h p r i u a c a s; R b i l s i l s a c s p r l s e n m x d-i m d l s o a p s i l r c i e .

Slide 48

Slide 48 text

♌ gambit:rails $ git grep undef_method actionpack/lib/abstract_controller/base.rb: undef_method :not_implemented actionpack/lib/action_controller/metal/responder.rb: undef_method(:to_json) if method_defined?(:to_json) actionpack/lib/action_controller/metal/responder.rb: undef_method(:to_yaml) if method_defined?(:to_yaml) actionpack/test/lib/controller/fake_models.rb: undef_method :to_json activemodel/lib/active_model/attribute_methods.rb: instance_methods.each { |m| undef_method(m) } activemodel/test/cases/observing_test.rb: undef_method :observed_classes activerecord/lib/active_record/associations/collection_proxy.rb: instance_methods.each { |m| undef_method m unless m.to_s =~ … activerecord/lib/active_record/attribute_methods/read.rb: instance_methods.each { |m| undef_method(m) } activerecord/lib/active_record/attribute_methods/read.rb: undef_method :__temp__ activerecord/lib/active_record/attribute_methods/read.rb: undef_method :__temp__ activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb: undef_method :select_rows activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb: undef_method :execute activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb: undef_method :select activerecord/test/cases/attribute_methods_test.rb: Object.send(:undef_method, :title) # remove test method from object activerecord/test/cases/attribute_methods_test.rb: topic.method(:id).owner.send(:undef_method, :id) activerecord/test/cases/finder_test.rb: undef_method(:find_or_create_by_name) if … activesupport/lib/active_support/basic_object.rb: undef_method :== activesupport/lib/active_support/basic_object.rb: undef_method :equal? activesupport/lib/active_support/basic_object.rb: undef_method(m) if m.to_s !~ /(?:^__|^nil\?$|^send$|^object_id$)/ activesupport/lib/active_support/callbacks.rb: undef_method(name) if method_defined?(name) activesupport/lib/active_support/core_ext/rexml.rb: undef_method :unnormalized activesupport/lib/active_support/deprecation/proxy_wrappers.rb: instance_methods.each { |m| undef_method m unless m =~ /^__|^object_id$/ } activesupport/lib/active_support/option_merger.rb: undef_method(method) if method !~ /^(__|instance_eval|class|object_id)/ activesupport/test/core_ext/duration_test.rb: class << k; undef_method :== end Rails…

Slide 49

Slide 49 text

• inherited • included • extended • append_features • const_missing • method_missing • method_added • method_removed • method_undefined • singleton_method_added • singleton_method_removed • singleton_method_undefined • ObjectSpace.define_finalizer(obj, aProc=proc()) • at_exit { block }

Slide 50

Slide 50 text

S q e c s

Slide 51

Slide 51 text

row_type = %w(odd even).cycle puts row_type.next puts row_type.next # … G h i m r w i e 8

Slide 52

Slide 52 text

sequence.next # 1 sequence.next # 2 sequence.next # 3 # … sequence.next # 1337

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

sequence = Enumerator.new do |yielder| number = 0 loop do number += 1 puts "-> #{Fiber.current.object_id}" yielder.yield number end end E d o s h e f ?! 8

Slide 55

Slide 55 text

sequence = Fiber.new do number = 0 loop do number += 1 Fiber.yield number end end def sequence.next resume end

Slide 56

Slide 56 text

#next #rewind #peek #each #feed

Slide 57

Slide 57 text

R e t o

Slide 58

Slide 58 text

“R e t o i t e n b e t w y t l a n w s o .” – ޸෉ࢠ

Slide 59

Slide 59 text

★ R e t o b d u e u L u z i I f r a i n n … ★ üb r d n e t K n t n e , ★ O j k e u d ★ i r E g n c a t n a f a e R e t o

Slide 60

Slide 60 text

N l -O j c

Slide 61

Slide 61 text

def display_user_info(user_name) user = PonyStore.find :users, name: user_name puts "---- USER ----" puts "Name: #{user.name}" puts "Age: #{user.age}" puts end user_names = ["Pinkie Pie", "Applejack"] user_names.each do |user_name| display_user_info user_name end

Slide 62

Slide 62 text

PonyStore.enable_null_objects! user_names.each do |user_name| display_user_info user_name end K i E c p i n-H n l n m h n t e d g 8

Slide 63

Slide 63 text

???

Slide 64

Slide 64 text

class PonyStore def self.find(collection, query) record = storage[collection].find_by query return record unless record.nil? return NullObject.new(collection.class) end end S a t nil g b n w r e n O j k z rüc , d s s c "s n v l " v r äl 8

Slide 65

Slide 65 text

class NullObject def initialize(original_class) original_class.instance_methods(false).each do |method_name| self.class.send(:define_method, method_name) { |*args| nil } end end end class User attr_accessor :name, :email, :address, :date_of_birth def age # non-trivial getter method end end

Slide 66

Slide 66 text

★ E d o e Mög i h e t n ★ Mäc t g , e n e a t W r z u e ★ E l u e e e a t Lös n e ★ N c t i m r s l t a a l s m c e ;-) d D n e M t !

Slide 67

Slide 67 text

O e M r T i g …

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

B n i g

Slide 70

Slide 70 text

★ K p e n e A s üh u g k n e t ★ E h l e Z g i u V r a l n, M t o e , self ★ W r e e z u t i Kernel#binding

Slide 71

Slide 71 text

class Pony def say_hello(a_binding = nil) eval('puts "Hello, my name is #{@name}"', a_binding || binding) end end @name = "Rainbow Dash" somepony.say_hello(binding) # Hello, my name is Rainbow Dash somepony = Pony.new somepony.say_hello # Hello, my name is.

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

T m l t s

Slide 74

Slide 74 text

class View def friend "Pinkie Pie" end def get_binding binding end end template = ERB.new <<-ERB <% @foo = 'bar' %> Welcome to Ruby is Magic! Let me introduce you to my good friend <%= friend %>. ERB puts template.result # (erb):3:in `': undefined local variable or method `friend' view = View.new puts template.result(view.get_binding) # Let me introduce you to my good friend Pinkie Pie. puts view.instance_variable_get("@foo") # bar

Slide 75

Slide 75 text

T a k ! D r B e e / @r i s r s_d r S b s i n C h e / @t s a h t ://g e s a m i c .d QaA “My Little Pony” © Hasbro Studios and DHX Media Vancouver