Slide 1

Slide 1 text

Brony User Group Cologne hosted by 21.11.2012

Slide 2

Slide 2 text

Ruby #12 Cupcakes

Slide 3

Slide 3 text

Lecker Was für Zwischendurch Klein

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Wir brauchen 20% mehr Structur!

Slide 7

Slide 7 text

Struct.new("Pony", :name, :type) # => Struct::Pony applejack = Struct::Pony.new("Applejack", "Earth Pony") # => #

Slide 8

Slide 8 text

class end # => Pony applejack = Pony.new("Applejack", "Earth Pony") # => # Pony < Struct.new(:name, :type)

Slide 9

Slide 9 text

??? Pony < Struct.new(:name, :type)

Slide 10

Slide 10 text

class MyStruct def self.new(*attr_names) Class.new do attr_accessor(*attr_names) def initialize(*attributes) self.class.instance_methods.grep(/.*=$/).each do |m| send(m, attributes.shift) end end end end end

Slide 11

Slide 11 text

class Pony < MyStruct.new(:name, :type) end rainbow_dash = Pony.new("Rainbow Dash", "Pegasus") # => #

Slide 12

Slide 12 text

Pony = Struct.new(:name, :type)

Slide 13

Slide 13 text

Aber Warum?!

Slide 14

Slide 14 text

Weil wir es können…

Slide 15

Slide 15 text

…und für “Domain Concepts”* *Steve Klabnik

Slide 16

Slide 16 text

class Pony attr_reader :name, :street, :street_number, :zip, :city def initialize(opts) @name = opts[:name] @street = opts[:street] @street_number = opts[:street_number] @zip = opts[:zip] @city = opts[:city] end end

Slide 17

Slide 17 text

class Pony attr_reader :name, :address Address = Struct.new(:street, :street_number, :zip, :city) def initialize(opts) @name = opts[:name] @address = Address.new(opts[:street], opts[:street_number], opts[:zip], opts[:city]) end end

Slide 18

Slide 18 text

OpenStruct

Slide 19

Slide 19 text

Container für Konfiguration

Slide 20

Slide 20 text

require 'ostruct' config = OpenStruct.new config.environment = "development" config.cache_store = "redis://127.0.0.1:6379" config.logger = STDOUT config.time_zone = "Europe/Berlin" p config # => #>, # time_zone="Europe/Berlin">

Slide 21

Slide 21 text

ActiveSupport::OrderedOptions

Slide 22

Slide 22 text

Sequenzen

Slide 23

Slide 23 text

“a particular order in which related events, movements, or things follow each other.” A sequence is…

Slide 24

Slide 24 text

Schon mal verwendet?

Slide 25

Slide 25 text

sequence.next # 1 sequence.next # 2 sequence.next # 3 sequence.next # 4 sequence.next # 5 ...

Slide 26

Slide 26 text

row_type.next # odd row_type.next # even row_type.next # odd row_type.next # even row_type.next # odd ...

Slide 27

Slide 27 text

names.next # Fluttershy names.next # Applejack names.next # Rainbow Dash names.next # Pinkie Pie names.next # Twighlight Sparkle names.next # Rarity

Slide 28

Slide 28 text

Enumerator

Slide 29

Slide 29 text

row_type = %w(odd even).cycle

Slide 30

Slide 30 text

names = ["Fluttershy", "Applejack", "Rainbow Dash", "Pinkie Pie", "Twighlight Sparkle", "Rarity"].each

Slide 31

Slide 31 text

sequence = Enumerator.new do |yielder| number = 0 loop do number += 1 yielder.yield number end end

Slide 32

Slide 32 text

#next #rewind #peek #feed #each

Slide 33

Slide 33 text

Alles hat ein Ende…

Slide 34

Slide 34 text

… names.next # Pinkie Pie names.next # Twighlight Sparkle names.next # Rarity names.next sequence.rb:46:in `next': iteration reached an end (StopIteration) ! from sequence.rb:46:in `'

Slide 35

Slide 35 text

class List def initialize(elements) @elements = elements end def each(&block) build_each(@elements.to_enum, &block) end def build_each(enum) while true begin next_value = enum.next yield next_value rescue StopIteration => iterator return iterator.result end end end end list = List.new [1,2,3,4] p list.each { |i| puts i }

Slide 36

Slide 36 text

Fun Fact loop do … end Fängt IMMER die StopIteration Exception

Slide 37

Slide 37 text

class List def initialize(elements) @elements = elements end def each(&block) build_each(@elements.to_enum, &block) end def build_each(enum) loop do yield enum.next end enum.to_a # Needed to make both versions equivalent end end list = List.new [1,2,3,4] p list.each { |i| puts i }

Slide 38

Slide 38 text

Alles hat ein Ende?

Slide 39

Slide 39 text

sequence = Enumerator.new do |yielder| number = 0 loop do number += 1 yielder.yield number end end Endlosschleife?! What in tarnation?

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

Lazy Enumerations

Slide 44

Slide 44 text

class Sequencer def initialize @start = 0 end def each loop do @start += 1 yield @start end end end

Slide 45

Slide 45 text

seq = Sequencer.new.to_enum ten_above_100 = [] while true n = seq.next ten_above_100 << n if n > 100 break if ten_above_100.size == 10 end p ten_above_100 # => [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]

Slide 46

Slide 46 text

seq.select { |x| x > 100 }.take(10) Endet nie…

Slide 47

Slide 47 text

Ruby 2.0 Feature

Slide 48

Slide 48 text

seq = Sequencer.new.to_enum p seq.lazy.select { |x| x > 100 }.take(10).to_a # => [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]

Slide 49

Slide 49 text

Structs sind praktisch, um “Domain Concepts” zu verpacken Wir benutzen ständig Sequenzen in Ruby Wenn erforderlich, können wir uns leicht infinite Sequenzen bauen

Slide 50

Slide 50 text

One More Thing…

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

✓Alle Getränke inklusive ✓Professionelle Reinigung ✓Hochwertige Büromöbel ✓100 Mbit Breitband-Internet ✓Nutzung von Drucker etc. ✓Erstklassiger Kaffee * inkl. 19% UmSt für pro Monat 359 € *

Slide 55

Slide 55 text

http://home-office-cologne.de

Slide 56

Slide 56 text

Thanks! Q & A? Dirk Breuer / @railsbros_dirk Sebastian Cohnen / @tisba ? “My Little Pony” © Hasbro Studios and DHX Media Vancouver rubyismagic.de

Slide 57

Slide 57 text

Just for Jakob…

Slide 58

Slide 58 text

Kapseln den Ausführungskontext Erhalten Zugriff auf Variablen, Methoden, self Werden erzeugt mit Kernel#binding

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

Okay …

Slide 61

Slide 61 text

… ERB!

Slide 62

Slide 62 text

require 'erb' class View def friend "Pinkie Pie" end def get_binding binding end end template = ERB.new <<-ERB 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' for main:Object # from /lib/ruby/1.9.1/erb.rb:838:in `eval' # from /lib/ruby/1.9.1/erb.rb:838:in `result' # from Ruby is Magic.rb/011-clip-show/code/erb_demo.rb:19:in `' puts template.result(View.new.get_binding) # Let me introduce you to my good friend Pinkie Pie.