Your SlideShare is downloading. ×
Steady with ruby
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Steady with ruby

91
views

Published on

An introductory talk about ruby's blocks, procs and lambdas, a sprinkling of meta-programming and a touch of modules

An introductory talk about ruby's blocks, procs and lambdas, a sprinkling of meta-programming and a touch of modules

Published in: Software, Technology, Education

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
91
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. @autonomous chris.spring@gmail.com Going steady with Ruby
  • 2. 1. {}, proc{}, ->{} 2. meta programming 3. modules
  • 3. 1) blocks,! procs and! lambdas
  • 4. (1..3).each do |i| puts i end # => 1 # => 2 # => 3 (1..3).each{ |i| puts i }
  • 5. (1..3).each do |i| puts i end # => 1 # => 2 # => 3 (1..3).each{ |i| puts i }
  • 6. def each for i in collection yield i end end
  • 7. def some_method(*arguments) # ... pre conditions yield( some_result ) # ... post conditions end
  • 8. def some_method(*arguments, &block) # ... pre conditions block.call( some_result ) # ... post conditions end
  • 9. file = File.new('credit_cards.txt', 'w') file.puts 'XXXX XXXX XXXX 5534' file.close File.new('credit_cards.txt', 'w') do |file| file.puts 'XXXX XXXX XXXX 5534' end Vs.
  • 10. proc{} vs lambda{}
  • 11. p = proc{ |i| puts "proc #{i}" } p.call("hey!") # => proc hey! ! ! ! ! l = lambda{ |i| puts "lamb #{i}" } l.call('yo!') # => lamb yo!
  • 12. p = proc{ |i| puts "proc #{i}" } l = lambda{ |i| puts "lamb #{i}" } ! (1..3).each(&p) # => proc 1 # => proc 2 # => proc 3 ! (1..3).each(&l) # => lamb 1 # => lamb 2 # => lamb 3
  • 13. def do_something(a_p, b_l, &block) print a_p.call() print block.call() print b_l.call() end ! ! p = proc{ "I'm a " } l = lambda{ " and I'm ok!" } ! ! do_something(p, l){ "lumberjack" } # => I'm a lumberjack and I'm ok!
  • 14. p.class # => Proc p.inspect # => “#<Proc:0x0000010194d8b8@(irb):97>" ! ! l.class # => Proc l.inspect # => "#<Proc:0x0000010190cd68@(irb):98 (lambda)>"
  • 15. p = proc{|i| puts i} p.call() # => nil ! p.call(1) # => 1 ! p.call(1, 2, 3) # => 1
  • 16. l = lambda{|i| puts i} l.call() # ArgumentError: wrong number of arguments (0 for 1) ! l.call(1) # => 1 ! l.call(1, 2, 3) # ArgumentError: wrong number of arguments (3 for 1)
  • 17. def proc_return p = proc{ return ‘Never ' } p.call 'Always ' end ! ! def lambda_return l = lambda{ return 'eat your vegetables!'} l.call 'give up!' end ! ! "#{proc_return} #{lambda_return}"
  • 18. Never give up!
  • 19. 2) META PROGRAMMING!
  • 20. send :<3
  • 21. class Statistics def initialize(account) @account = account end ! def increment_counts(metric, by=1) case metric when :sent @account.increment_sent_count(by) when :viewed @account.increment_viewed_count(by) when :bounced @account.increment_bounced_count(by) end end end
  • 22. class Statistics def initialize(account) @account = account end ! def increment_counts(metric, by=1) method = "increment_#{metric}_count" @account.send(method, by) end end
  • 23. class Account # ... private def schedule_billing # ... end end ! class BillingRunner def initialize(account) @account end ! def run! # ... @account.send(:schedule_billing) # ... end end
  • 24. class Account # ... private def schedule_billing # ... end end ! class BillingRunner def initialize(account) @account end ! def run! # ... @account.send(:schedule_billing) # ... end end
  • 25. define_method :awesome {}
  • 26. class User def admin! @role = :admin end ! def admin? @role == :admin end ! def client! @role = :client end ! def client? @role == :client end end
  • 27. class User ROLES = %i(admin client) ! ROLES.each do |role| define_method "#{role}?" do @role == role end ! define_method "#{role}!" do @role = role end end end
  • 28. %i(admin client supervisor technician vendor manager)
  • 29. method_missing m, *args, &b
  • 30. class KeyValueStore def initialize(store={}) @store = store end ! def insert(key, value) @store[key] = value end end ! store = KeyValueStore.new store.respond_to?(:insert) # => true ! store.insert(:one, 1) ! m = store.method(:insert) m.call(:two, 2) ! store.instance_variable_get('@store') # => {one: 1, two: 2}
  • 31. class KeyValueStore def initialize(store={}) @store = store end ! def insert(key, value) @store[key] = value end end ! store = KeyValueStore.new store.respond_to?(:insert) # => true ! store.insert(:one, 1) ! m = store.method(:insert) m.call(:two, 2) ! store.instance_variable_get('@store') # => {one: 1, two: 2}
  • 32. class KeyValueStore # ... ! def method_missing(method_name, *args, &block) if @store.respond_to?(method_name) @store.send(method_name, *args, &block) else super end end ! def respond_to_missing?(method_name, include_private) @store.respond_to?(method_name) || super end end
  • 33. kv = KeyValueStore.new kv.insert(:three, 3) ! kv.respond_to?(:include?) # => true kv.include?(:three) # => true ! m = kv.method(:include?) m.call(:four) # => false ! kv.keys # => [:three] kv.values # => [3]
  • 34. 3) Modules
  • 35. module Mathematics class Plane # ... end end ! ! module Airport class Plane # ... end end
  • 36. module TehForce def sense '... a disturbance in the force' end end ! class Person include TehForce # ... end ! p = Person.new p.sense # => "... a disturbance in the force"
  • 37. Person = Class.new() p = Person.new ! ! p.sense # NoMethodError: undefined method `sense' … ! ! p.extend TehForce p.sense # => "... a disturbance in the force"
  • 38. module UserDianostics def perform_diagnostics check_counts validate_dates find_orphans end ! # .... end ! user = User.find(some_id) user.extend UserDianostics user.perform_diagnostics
  • 39. module RepublicPersonnel def storm_trooper Person.new end end ! ! class CloningVat extend RepublicPersonnel end ! ! CloningVat.storm_trooper # => #<Person:0x0000010187c150>
  • 40. Person = Class.new() CloningVat = Class.new() ! ! CloningVat.storm_trooper # => NoMethodError: undefined method `storm_trooper' … ! ! CloningVat.extend RepublicPersonnel CloningVat.storm_trooper # => #<Person:0x0000010187c150>
  • 41. include and extend?
  • 42. module SomeMixin module ClassMethods # ... end module InstanceMethods # ... end def self.included(receiver) receiver.extend ClassMethods receiver.send :include, InstanceMethods end end
  • 43. A contrived example…
  • 44. admin = Administrator.new admin.allowed_to_toggle_alarm? # => true admin.allowed_to_visit_facebook? # => false ! lacky = Lacky.new lacky.allowed_to_be_seen? # => true lacky.allowed_to_be_heard? # => false lacky.allowed_to_make_eye_contact? # => false
  • 45. class Administrator include Permissions ! can :toggle_alarm end ! admin = Administrator.new admin.allowed_to_toggle_alarm? # => true admin.allowed_to_visit_facebook? # => false
  • 46. class Lacky include Permissions ! can :be_seen end ! lacky = Lacky.new lacky.allowed_to_be_seen? # => true lacky.allowed_to_be_heard? # => false
  • 47. module Permissions module ClassMethods def can(do_something) define_method "allowed_to_#{do_something}?" do true end end end ! module InstanceMethods def method_missing(*args, &block) method_name = args[0] if method_name && method_name =~ /allowed_to_.*?/ false else super end end end ! def self.included(receiver) receiver.extend ClassMethods receiver.send :include, InstanceMethods end end
  • 48. Thanks for Listening
  • 49. Questions?