Metaprogramming With Ruby

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

1 comments

Comments 1 - 1 of 1 previous next Post a comment

  • + guest17411b guest17411b 2 years ago
    Hi Julie and Farooq,



    Excellent slide-show. I was just building an algebraic expression evaluator for my 11-yo granddaughter. I was her to fire it up and enter stuff like x=5, y=6, ? x*y on separate lines and get back 30. I was able to method_missing to to define @x and initialize it to 5, but I couldn’t figure out how to define a getter for x, etc. Your slides introduced me to define_method. I think that’ll do the job. Thanks for posting your slides.
Post a comment
Embed Video
Edit your comment Cancel

13 Favorites

Metaprogramming With Ruby - Presentation Transcript

  1. Metaprogramming with Ruby Julie Yaunches Farooq Ali
  2. What is Metaprogramming?
    • Code that writes code
    • Know Thyself
    • Reflection.kind_of? Metaprogramming
    • Compile-time vs. Runtime
  3. Metaprogramming == Programming
    • No natural separation
    • Ruby is interpreted, not compiled
    • Everything’s an object. Even classes!
    • Extensible type system
    • "Meta, shmeta! Learning Ruby isn’t like scaling a mountain. It’s more like exploring a plain. "
    • - David Black
  4. Exploring the plain define_method alias_method foo.send :bar instance_variable_get class_eval instance_eval module_eval instance_variable_set eval block.call Class.new method_missing class << self block.binding Foo.instance_methods method_added method_removed
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  5. Ruby Object Model I
    • Everything is an instance of Object
    • Every object has a number of things:
        • klass, superclass, methods
      • Developer = Class.new
      • julie = Developer.new
  6. Ruby Object Model I
    • Module – a collection of methods and constants
      • Methods can be instance methods or module methods
      • Modules can be ‘mixedin’ to a class.
        • module British
        • def goes_to_pub
        • “ I love beer and geeky talk”
        • end
        • end
        • class Developer
        • include British
        • end
        • julie.goes_to_pub => “I love beer and geeky talk”
  7. Ruby Object Model I
    • When you create a module, it’s methods become available to the instances of the class via a proxy class.
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  8. Object Introspection
    • Instance variables
    • Instance Methods
    • Class scope via singleton class
  9. Object Introspection: Instance Variables > @event = 'Away Day' > instance_variable_get '@event' => &quot;Away Day&quot; > instance_variable_set '@region', 'UK' > @region => &quot;UK&quot; > instance_variables => [&quot;@event&quot;, &quot;@region&quot;]
  10. Object Introspection: Methods > 'Away Day’. methods => [&quot;capitalize&quot;, &quot;split&quot;, &quot;strip&quot;, …] > 5. public_methods => [&quot;+&quot;, &quot;/&quot;, &quot;integer?&quot;, …]
  11. Object Introspection: Methods > 'abc'.method(:capitalize) => #<Method: String#capitalize> class method strip capitalize String gsub split class method unbind arity Method to_proc call
  12.  
  13. Introspection in Action class Person def initialize(name, age, sex) @name = name @age = age @sex = sex end end Person.new('Farooq', 23, :male) Did we just think in a for-loop?!
  14. Introspection in Action class Person def initialize(attributes) attributes.each do |attr, val| instance_variable_set(&quot;@#{attr}&quot;, val) end end end Person.new :name => 'Farooq', :age => '23', :sex => :male
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
    • Most common usage… Loop extraction… means of iterating
    • Blocks are basically nameless functions. You can pass a a block to another function, and then that function can invoke the passed-in nameless function.
    • Callbacks and hooks (will see later)
    • Can be passed all over the place for really any sort of need.
    Blocks
  15. Blocks
    • Blocks are basically nameless functions. You can pass a a block to another function, and then that function can invoke the passed-in nameless function.
      • def foo
      • yield
      • end
      • foo {puts “foo”} => “foo”
      • foo {puts “bar”} => “bar”
    • Iterating through a collection
      • Records.each do |record|
      • print_title
      • end
    • Encapsulating error prone procedures
      • open(“some_file”) do |input|
      • input.each_line do |line|
      • process_input_line line
      • end
      • end
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
    • Calling methods dynamically
    • Convention-Oriented coding
    • Defining them on the fly
    • Writing declarative code
    Dynamic Methods
  16. Calling methods dynamically
    • > a = &quot;Hello World!&quot;
    • => &quot;Hello World!&quot;
    • > a.downcase
    • => &quot;hello world!&quot;
    • > a.send(:downcase)
    • => &quot;hello world!&quot;
  17.  
  18. Calling methods dynamically: Why should I care?
    • Parameterized method names
    • Callbacks and Observers
    • Convention-oriented code
    • Working with method collections
    • and more…
  19. Parameterized method names
    • controller:
    • @person = Person.new('Farooq')
    • view:
    • <%= text_field :person, :name %>
    def text_field(obj, method) iv = instance_variable_get &quot;@#{obj}&quot; val = iv.send(method) &quot;<input type='text' value='#{val}'>&quot; end
  20. Callbacks
    • class VaultController < BankController
    • before_filter :authorize
    • private
    • def authorize
    • user.can_access?(vault)
    • end
    • end
  21. Callbacks
    • class SymbolFilter < Filter
    • def initialize(filter)
    • @filter = filter
    • end
    • def call(controller, &block)
    • controller.send(@filter, &block)
    • end
    • end
  22. Convention-Oriented Coding
    • class CreditCard
    • def validate
    • validate_number
    • validate_expiration
    • end
    • private
    • def validate_number
    • ...
    • end
    • def validate_expiration
    • ...
    • end
    • end
  23. Convention-Oriented Coding
    • def validate
    • methods.grep /^validate_/ do |m|
    • self.send m
    • end
    • end
  24. Convention-Oriented Coding
    • class CreditCard
    • validate :number, :expiration
    • end
  25. Convention-Oriented Coding
    • def validate(*validations)
    • validations.each do |v|
    • self.send &quot;validate_#{v}&quot;
    • end
    • end
  26. You can define methods on the fly too! define_method :say_hello do puts &quot;Hello World!&quot; end
  27. define_method
    • Defines an instance method on a class
    • Can define class methods via singleton
    • Great for writing declarative code
  28.  
  29. Dynamic Method Definition in Action class Person attr_reader :name, sex end class Person { string name, sex; public string Name { get {return name;} } public string Sex { get {return sex;} } }
  30. Dynamic Method Definition in Action class Object def Object.attr_reader(*attrs) attrs.each do |attr| define_method(attr) do instance_variable_get(&quot;@#{attr}&quot;) end end end end
  31. Dynamic Method Definition in Action class Object def Object.attr_reader(*attrs) attrs.each do |attr| define_method(attr) do instance_variable_get(&quot;@#{attr}&quot;) end end end end
  32. Another example: Lazy Loading class Person List<Person> friends; public List<Person> Friends { get { friends = friends ?? LoadFriends(); return friends; } }
  33. Lazy Loading class Person lazy_loaded_attr :friends end
  34. Lazy Loading class Object def self.lazy_loaded_attr(*attrs) attrs.each do |attr| define_method(attr) do eval &quot;@#{attr} ||= load_#{attr}&quot; end end end end
  35. Lazy Loading class Person lazy_loaded_attr :friends, :children, :parents end class Person List<Person> friends, children, parents; public List<Person> Friends { get { friends = friends ?? LoadFriends(); return friends; } } public List<Person> Children { get { children = children ?? LoadChildren(); return children; } } public List<Person> Parents { get { parents = parents ?? LoadParents(); return parents; } } }
  36. Declarative code class Album < ActiveRecord::Base has_many :tracks belongs_to :artist acts_as_taggable has_many :lyrics, :through => :tracks end
  37. Declarative code with define_method class Album < ActiveRecord::Base has_many :tracks end class Album < ActiveRecord::Base def tracks Track.find :all, :conditions => &quot;album_id=#{id}&quot; end end define_method :tracks …
  38. Declarative code with define_method class ActiveRecord::Base def self.has_many(records) define_method(records) do foreign_key = &quot;#{self.name.underscore}_id&quot; klass = records.to_s.classify.constantize klass.find :all, :conditions => &quot;#{foreign_key}=#{id}&quot; end end end
  39. Person Person walk() define_method :walk define_method :everyone ? Person everyone() Define instance method: Define class method:
  40. Person Person walk() define_method :walk define_method :everyone Person' Person' everyone() Define instance method: Define class method:
  41. Person Person walk() define_method :walk define_method :everyone Person' Person' everyone() Define instance method: Define class method: Person everyone()
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  42. Ruby Object Model II
    • You can open any object and define methods on it.
      • Developer = Class.new Developer.instance_eval do def pairing “julie and farooq are pairing&quot; end end
      • Developer.class_eval do def write_code “type type type&quot; end end Developer.write_code #=> undefined method ‘write_code’ for Foo:Class Developer.new. write_code #=> “type type type&quot; Developer.pairing #=> &quot; julie and farooq are pairing&quot; Developer.new.pairing #=> undefined method ‘baz’ for #<Foo:0x7dce8>
  43. Ruby Object Model II
    • We’ve now opened and defined methods on both the instance of Class Developer and all instances of Class Developer.
      • When you define methods on an instance of an object, you are defining them on it’s ‘metaclass’ or singleton.
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  44. Method Aliasing
    • Clones a method
    • Popularly used in decorators
      • AOP &quot;around advice&quot;
      • LISP around method combinator
    • Monkey patches
    class LoginService alias_method :original_login, :login end
  45. Decorator Pattern with Aliasing class LoginService alias_method :original_login, :login def login(user,pass) log_event &quot;#{user} logging in&quot; original_login(user,pass) end end
  46. Decorator Pattern with Aliasing class LoginService alias_method_chain :login, :logging def login_with_logging(user,pass) log_event &quot;#{user} logging in&quot; login_without_logging(user,pass) end end
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  47. Evaluation Techniques
    • Evaluate code at runtime
    • In instance and class scopes
    • With different block bindings
    • eval, instance_eval, class_eval, module_eval
  48. eval
    • Evaluates a string
    > eval &quot;foo = 5&quot; > foo => 5
    • Optional binding
    def get_binding(str) return binding end str = &quot;hello&quot; eval &quot;str + ' Fred'&quot; ! &quot;hello Fred&quot; eval &quot;str + ' Fred'&quot;, get_binding(&quot;bye&quot;) ! &quot;bye Fred&quot;
    • Ruby object model I: classes, objects, modules and blocks
    • Object introspection
    • Blocks and the strategy pattern
    • Dynamic methods
    • Ruby object model II: singletons and open classes
    • Method aliasing and the decorator pattern
    • Evaluation techniques
    • Object lifecycle hooks and method_missing
    Outline
  49. Hooks
    • Allow you to trap some event, such as object creation…
      • Example – adding a timestamp to every object created. (Taken from the pickaxe)
          • class Object
          • attr_accessor :timestamp
          • end
          • class Class
          • alias_method :old_new, :new
          • def new(*args)
          • result = old_new(*args)
          • result.timestamp = Time.now
          • result
          • end
          • end
  50. Hooks
    • You can know when a Module was included in another Object definition.
    • module A
    • def A.included(mod)
    • puts &quot;#{self} included in #{mod}“
    • end
    • end
    • module Enumerable
    • include A
    • end
    • This is done via a call to append_features on the module doing the including
  51. Hooks
    • method_missing
    • method_added
    • method_removed
    • You can hook into any of these and perform some operation when something happens to object under consideration.
      • class Foo
      • def method_missing(methodname, *args) #log something
      • #handle in some way
      • end end
  52. Hooks
    • Can allow you to hook into how your plugins are intialized with Rails.
    • Rails uses something called Rails::Plugin::Loader
      • You can hook into this
        • Rails::Initializer.run do |config|
        • config.plugin_loader = PluginLoaderWithDependencies
        • End
    • Similarly, hooking into other framework type stuff (like ActiveRecord or even Subversion) is possible
  53. Metaprogramming with Ruby
    • No longer black magic
    • Fresh design patterns
    • Declarative programming
    • Higher level of abstraction
    • Tone down the YAGNI
  54. Questions?

+ faro00oqfaro00oq, 3 years ago

custom

5400 views, 13 favs, 7 embeds more stats

Presented at the November '07 ThoughtWorks UK Away more

More info about this document

© All Rights Reserved

Go to text version

  • Total Views 5400
    • 5030 on SlideShare
    • 370 from embeds
  • Comments 1
  • Favorites 13
  • Downloads 188
Most viewed embeds
  • 281 views on http://www.jroller.com
  • 80 views on http://jroller.com
  • 3 views on http://uptolife.blogspot.com
  • 2 views on http://localhost:3000
  • 2 views on http://203.208.39.132

more

All embeds
  • 281 views on http://www.jroller.com
  • 80 views on http://jroller.com
  • 3 views on http://uptolife.blogspot.com
  • 2 views on http://localhost:3000
  • 2 views on http://203.208.39.132
  • 1 views on http://static.slideshare.net
  • 1 views on http://209.85.229.132

less

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

Cancel
File a copyright complaint
Having problems? Go to our helpdesk?

Categories