@autonomous
chris.spring@gmail.com
Going steady with
Ruby
1. {}, proc{}, ->{}
2. meta programming
3. modules
1) blocks,!
procs and!
lambdas
(1..3).each do |i|
puts i
end
# => 1
# => 2
# => 3
(1..3).each{ |i| puts i }
(1..3).each do |i|
puts i
end
# => 1
# => 2
# => 3
(1..3).each{ |i| puts i }
def each
for i in collection
yield i
end
end
def some_method(*arguments)
# ... pre conditions
yield( some_result )
# ... post conditions
end
def some_method(*arguments, &block)
# ... pre conditions
block.call( some_result )
# ... post conditions
end
file = File.new('credit_cards.txt', 'w')
file.puts 'XXXX XXXX XXXX 5534'
file.close
File.new('credit_cards.txt', 'w') do |...
proc{} vs lambda{}
p = proc{ |i| puts "proc #{i}" }
p.call("hey!")
# => proc hey!
!
!
!
!
l = lambda{ |i| puts "lamb #{i}" }
l.call('yo!')
# ...
p = proc{ |i| puts "proc #{i}" }
l = lambda{ |i| puts "lamb #{i}" }
!
(1..3).each(&p)
# => proc 1
# => proc 2
# => proc 3
...
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 = l...
p.class
# => Proc
p.inspect
# => “#<Proc:0x0000010194d8b8@(irb):97>"
!
!
l.class
# => Proc
l.inspect
# => "#<Proc:0x000001...
p = proc{|i| puts i}
p.call()
# => nil
!
p.call(1)
# => 1
!
p.call(1, 2, 3)
# => 1
l = lambda{|i| puts i}
l.call()
# ArgumentError: wrong number of arguments
(0 for 1)
!
l.call(1)
# => 1
!
l.call(1, 2, 3)
...
def proc_return
p = proc{ return ‘Never ' }
p.call
'Always '
end
!
!
def lambda_return
l = lambda{ return 'eat your vegeta...
Never give up!
2) META PROGRAMMING!
send :<3
class Statistics
def initialize(account)
@account = account
end
!
def increment_counts(metric, by=1)
case metric
when :sen...
class Statistics
def initialize(account)
@account = account
end
!
def increment_counts(metric, by=1)
method = "increment_#...
class Account
# ...
private
def schedule_billing
# ...
end
end
!
class BillingRunner
def initialize(account)
@account
end
...
class Account
# ...
private
def schedule_billing
# ...
end
end
!
class BillingRunner
def initialize(account)
@account
end
...
define_method :awesome {}
class User
def admin!
@role = :admin
end
!
def admin?
@role == :admin
end
!
def client!
@role = :client
end
!
def client?
...
class User
ROLES = %i(admin client)
!
ROLES.each do |role|
define_method "#{role}?" do
@role == role
end
!
define_method "...
%i(admin client supervisor technician vendor manager)
method_missing m, *args, &b
class KeyValueStore
def initialize(store={})
@store = store
end
!
def insert(key, value)
@store[key] = value
end
end
!
sto...
class KeyValueStore
def initialize(store={})
@store = store
end
!
def insert(key, value)
@store[key] = value
end
end
!
sto...
class KeyValueStore
# ...
!
def method_missing(method_name, *args, &block)
if @store.respond_to?(method_name)
@store.send(...
kv = KeyValueStore.new
kv.insert(:three, 3)
!
kv.respond_to?(:include?) # => true
kv.include?(:three) # => true
!
m = kv.m...
3) Modules
module Mathematics
class Plane
# ...
end
end
!
!
module Airport
class Plane
# ...
end
end
module TehForce
def sense
'... a disturbance in the force'
end
end
!
class Person
include TehForce
# ...
end
!
p = Person....
Person = Class.new()
p = Person.new
!
!
p.sense
# NoMethodError: undefined method `sense' …
!
!
p.extend TehForce
p.sense
...
module UserDianostics
def perform_diagnostics
check_counts
validate_dates
find_orphans
end
!
# ....
end
!
user = User.find...
module RepublicPersonnel
def storm_trooper
Person.new
end
end
!
!
class CloningVat
extend RepublicPersonnel
end
!
!
Clonin...
Person = Class.new()
CloningVat = Class.new()
!
!
CloningVat.storm_trooper
# => NoMethodError: undefined method
`storm_tro...
include and extend?
module SomeMixin
module ClassMethods
# ...
end
module InstanceMethods
# ...
end
def self.included(receiver)
receiver.exten...
A contrived example…
admin = Administrator.new
admin.allowed_to_toggle_alarm? # => true
admin.allowed_to_visit_facebook? # => false
!
lacky = L...
class Administrator
include Permissions
!
can :toggle_alarm
end
!
admin = Administrator.new
admin.allowed_to_toggle_alarm?...
class Lacky
include Permissions
!
can :be_seen
end
!
lacky = Lacky.new
lacky.allowed_to_be_seen? # => true
lacky.allowed_t...
module Permissions
module ClassMethods
def can(do_something)
define_method "allowed_to_#{do_something}?" do
true
end
end
e...
Thanks for
Listening
Questions?
Steady with ruby
Steady with ruby
Steady with ruby
Steady with ruby
Upcoming SlideShare
Loading in …5
×

Steady with ruby

473 views

Published on

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
473
On SlideShare
0
From Embeds
0
Number of Embeds
22
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Steady with ruby

  1. 1. @autonomous chris.spring@gmail.com Going steady with Ruby
  2. 2. 1. {}, proc{}, ->{} 2. meta programming 3. modules
  3. 3. 1) blocks,! procs and! lambdas
  4. 4. (1..3).each do |i| puts i end # => 1 # => 2 # => 3 (1..3).each{ |i| puts i }
  5. 5. (1..3).each do |i| puts i end # => 1 # => 2 # => 3 (1..3).each{ |i| puts i }
  6. 6. def each for i in collection yield i end end
  7. 7. def some_method(*arguments) # ... pre conditions yield( some_result ) # ... post conditions end
  8. 8. def some_method(*arguments, &block) # ... pre conditions block.call( some_result ) # ... post conditions end
  9. 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. 10. proc{} vs lambda{}
  11. 11. p = proc{ |i| puts "proc #{i}" } p.call("hey!") # => proc hey! ! ! ! ! l = lambda{ |i| puts "lamb #{i}" } l.call('yo!') # => lamb yo!
  12. 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. 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. 14. p.class # => Proc p.inspect # => “#<Proc:0x0000010194d8b8@(irb):97>" ! ! l.class # => Proc l.inspect # => "#<Proc:0x0000010190cd68@(irb):98 (lambda)>"
  15. 15. p = proc{|i| puts i} p.call() # => nil ! p.call(1) # => 1 ! p.call(1, 2, 3) # => 1
  16. 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. 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. 18. Never give up!
  19. 19. 2) META PROGRAMMING!
  20. 20. send :<3
  21. 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. 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. 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. 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. 25. define_method :awesome {}
  26. 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. 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. 28. %i(admin client supervisor technician vendor manager)
  29. 29. method_missing m, *args, &b
  30. 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. 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. 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. 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. 34. 3) Modules
  35. 35. module Mathematics class Plane # ... end end ! ! module Airport class Plane # ... end end
  36. 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. 37. Person = Class.new() p = Person.new ! ! p.sense # NoMethodError: undefined method `sense' … ! ! p.extend TehForce p.sense # => "... a disturbance in the force"
  38. 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. 39. module RepublicPersonnel def storm_trooper Person.new end end ! ! class CloningVat extend RepublicPersonnel end ! ! CloningVat.storm_trooper # => #<Person:0x0000010187c150>
  40. 40. Person = Class.new() CloningVat = Class.new() ! ! CloningVat.storm_trooper # => NoMethodError: undefined method `storm_trooper' … ! ! CloningVat.extend RepublicPersonnel CloningVat.storm_trooper # => #<Person:0x0000010187c150>
  41. 41. include and extend?
  42. 42. module SomeMixin module ClassMethods # ... end module InstanceMethods # ... end def self.included(receiver) receiver.extend ClassMethods receiver.send :include, InstanceMethods end end
  43. 43. A contrived example…
  44. 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. 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. 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. 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. 48. Thanks for Listening
  49. 49. Questions?

×