in Tokyo, Japan. • I’m a Canadian from Montréal. • I work at a company called Degica. • I’m the author of a gem called Mobility. • I blog at dejimata.com.
in which computer programs have the ability to treat programs as their data 3. a way for a program to find out things about itself, or other programs 4. a bag of tricks
define_method name do @attributes.fetch(name) end define_method "#{name}=" do |value| @attributes[name] = value end end end class Model def initialize; @attributes = {}; end def self.define_attribute(name) define_method name do @attributes.fetch(name) end define_method "#{name}=" do |value| @attributes[name] = value end end end control
= Talk.new talk.title = "Metaprogramming for Generalists" talk.title #=> "Metaprogramming for Generalists" talk.abstract = "It conjures up images of..." talk.abstract #=> "It conjures up images of..." abstraction is transparent control
@attributes.fetch(name) end def set_attribute(name, value) @attributes[name] = value end end class Model def initialize; @attributes = {}; end def get_attribute(name) @attributes.fetch(name) end def set_attribute(name, value) @attributes[name] = value end end knockout
message - speaks in language of domain - abstraction visible - send as argument - speaks in language of abstraction - unknowns refer to code - hard to understand - unknowns do not refer to code - easier to understand
software is to write generic software. Instead of designing a single API that completely handles a specific case, you write multiple APIs that handle smaller, more generic parts of that use case and then handling the entire case is just gluing those parts together.” “ “The Development of Sequel”, May 2012
@street, @city, @country = street, city, country end # ... def ==(other) other.is_a?(self.class) && other.street == street && other.city == city && other.country == country end end # activerecord/test/models/customer.rb:15
def longitude gps_location.split("x").last end def ==(other) other.latitude == latitude && other.longitude == longitude end end # activerecord/test/models/customer.rb:45
other.city == city && other.country == country end end class GpsLocation def ==(other) other.latitude == latitude && other.longitude == longitude end end
send(:city) && other.send(:country) == send(:country) end end class GpsLocation def ==(other) other.send(:latitude) == send(:latitude) && other.send(:longitude) == send(:longitude) end end
Address extend Equalizer equalize :street, :city, :country end class GpsLocation extend Equalizer equalize :latitude, :longitude end class GpsLocation extend Equalizer equalize :latitude, :longitude end require "equalizer" class AM::Type::Value extend Equalizer equalize :precision, :scale, :limit end class AM::Type::Value extend Equalizer equalize :precision, :scale, :limit end class AR::Attribute extend Equalizer equalize :name, :value_before_type_cast, :type end class AR::Attribute extend Equalizer equalize :name, :value_before_type_cast, :type end class AM::AttributeSet extend Equalizer equalize :attributes end class AM::AttributeSet extend Equalizer equalize :attributes end class AR::ConnectionAdapters::Column extend Equalizer equalize :attributes_for_hash end class AR::ConnectionAdapters::Column extend Equalizer equalize :attributes_for_hash end class AM::AttributeSet::Builder extend Equalizer equalize :materialize end class AM::AttributeSet::Builder extend Equalizer equalize :materialize end class AR::Relation::WhereClause extend Equalizer equalize :predicates end class AR::Relation::WhereClause extend Equalizer equalize :predicates end
Google Maps • Visualization of dry-rb gems network created using Graph Commons (graphcommons.com) • Image of Ruby from: – http://pngimg.com/download/22155