method_missing
Handle calls to methods that do not already exist
method_missing
class Container
def package!
puts 'Packaged'
end
def method_missing(method_name)
if method_name == :shipit!
puts 'SHIPIT!'
end
end
end
box = Container.new
box.package! # => Packaged
box.shipit! # => SHIPIT!
activerecord-deprecated_finders
User.find_by_email(email) # Rails 3 deprecated finders available by default
vs
User.find_by(:email, email) # Rails 4 without deprecated finders
respond_to_missing?
Container.new.respond_to? :shipit! # => false
Container.new.method :shipit! # => NameError: undefined method 'shipit!'
class Container
def method_missing(method_name)
if method_name == :shipit!
puts 'SHIPIT!'
end
end
def respond_to_missing?(method_name, include_private = false)
method_name == :shipit! ? true : false
end
end
Container.new.respond_to? :shipit! # => true
Container.new.method :shipit! # => <Method: Container#shipit!>
You should define respond_to_missing?method_missing
method_added
class Container
def self.method_added(method_name)
puts "#{method_name} is now available!"
end
def shipit!; end # => shipit! is now available!
end
method_removed
class Container
def self.method_removed(method_name)
puts "#{method_name} was removed"
end
def shipit!; end
remove_method :shipit! # => shipit! was removed
end
method_undefined
class Container
def self.method_undefined(method_name)
puts "#{method_name} was undefined"
end
def shipit!; end
undef_method :shipit! # => shipit! was undefined
end
singleton_method_added
class Container
def self.singleton_method_added(method_name)
puts "#{method_name} was added"
end # => singleton_method_added was added
def self.shipit!; end # => shipit! was added
end
singleton_method_removed
class Container
def self.singleton_method_removed(method_name)
puts "#{method_name} was removed"
end
def self.shipit!; end
end
class << Container
remove_method :shipit! # => shipit! was removed
end
singleton_method_undefined
class Container
def self.singleton_method_undefined(method_name)
puts "#{method_name} was undefined"
end
def self.shipit!; end
end
class << Container
undef_method :shipit! # => shipit! was undefined
end
method_missing
respond_to_missing?
method_added
method_removed
method_undefined
singleton_method_added
singleton_method_removed
singleton_method_undefined
inherited
class Container
def self.inherited(subclass)
puts "#{subclass} is now inheriting from #{self.name}"
end
end
class Box < Container; end # => Box is now inheriting from Container
module Shippable
def shipit!
puts 'SHIPIT!'
end
end
class Container
include Shippable
end
Container.new.shipit! # => SHIPIT!
include is for adding instance methodsextend is for adding class methods
append_features
module Shippable
def self.append_features(other)
puts "The features of #{self} were appended to #{other}"
super
end
def shipit!
puts 'SHIPIT!'
end
end
class Container
include Shippable # => The features of Shippable were appended to Container
end
included
module Shippable
def self.included(other)
puts "#{other} included the features of #{self}"
end
end
class Container
include Shippable # => Container included the features of Shippable
end
class HardWorker
include Sidekiq::Worker
def perform
puts "Work!"
end
end
Behind the scenes
module Sidekiq
module Worker
def self.included(base)
base.extend(ClassMethods)
base.class_attribute :sidekiq_options_hash
base.class_attribute :sidekiq_retry_in_block
base.class_attribute :sidekiq_retries_exhausted_block
end
module ClassMethods
def perform_async(*args)
...
end
end
end
end
ActiveSupport::Concern
module Shippable
extend ActiveSupport::Concern
included do
extend ClassMethods
end
module ClassMethods
end
end
You can get some nicer syntax if you extend from ActiveSupport::Concern
include
module Shippable
def shipit!
puts 'shipit!'
end
end
class Container
include Shippable
def shipit!
puts 'SHIPIT!'
super
end
end
Container.new.shipit! # => SHIPIT!
# => shipit!
prepend
module Shippable
def shipit!
puts 'shipit!'
super
end
end
class Container
prepend Shippable
def shipit!
puts 'SHIPIT!'
end
end
Container.new.shipit! # => shipit!
# => SHIPIT!
prepend_features
module Shippable
def self.prepend_features(other)
puts "The features of #{self} were prepend to #{other}"
super
end
def shipit!
puts 'SHIPIT!'
end
end
class Container
prepend Shippable # => Features of Shippable were prepended to Container
end
module Shippable
def shipit!
puts 'SHIPIT!'
end
end
class Container
extend Shippable
end
Container.shipit! # => SHIPIT!
extended
module Shippable
def self.extended(other)
puts "#{other} was extended with #{self}"
super
end
def shipit!
puts 'SHIPIT!'
end
end
class Container
extend Shippable # => Container was extended with Shippable
end
extend_object
module Shippable
def self.extend_object(other)
puts "#{other} was extended with #{self}"
super
end
def shipit!
puts 'SHIPIT!'
end
end
class Container
extend Shippable # => Container was extended with Shippable
end
Similar to append_features, and prepend_featuresinitialize
class Container
def initialize
puts 'Ready to Shipit!'
end
end
Container.new # => Ready to Shipit!
initialize_copy
class Container
attr_accessor :width
def initialize
@width = 4
end
def initialize_copy(other)
other.width = 2
end
end
a = Container.new
a.width # => 4
b = a.dup
b.width # => 2
const_missing
class Container
def initialize
SHIPIT
end
def self.const_missing(con)
puts "#{con} was missing"
end
end
Container.new # => SHIPIT was missing
Similar to method_missing but for constants
marshal_dump
marshal_load
class Container
def marshal_dump
puts "Dumping Container"
end
def marshal_load(data)
puts "Loading Container"
end
end
dumped = Marshal.dump Container.new # => Dumping Container
Marshal.load(dumped) # => Loading Container
These have to be interchangeableinherited
include/included/append_features
extend/extended/extend_object
prepend/prepended/prepend_features
initialize
initialize_copy
const_missing
class Container
def +(other)
if other.is_a? String
puts other
end
end
end
Container.new + 'shipit!' # => shipit!
Pretty impractical right?
Date.today # => Mon, 28 Oct 2013
Date.today + 5 # => Sat, 02 Nov 2013
nil.to_i # => 0
Allows us to add dates together really easily
* ** % - -@ +@ + / += -= *= /= **= =~ !~ << >> <=> [] []= != == === < > <= >= | ^ & ~
* Multiply and Splat
& Binary AND and Symbol#to_proc
<< Bitwise shift and append to Strings and Arrays
|| ||= && &&= and or not = -> . .. ... :: () {}
trace_var
trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
$_ = 'hello' # => $_ is now 'hello'
$_ = ' there' # => $_ is now ' there'
Signal.trap
❯ irb
2.0.0-p247 :001 > Signal.trap("INT") { |signo| puts Signal.signame(signo) }
2.0.0-p247 :002 > INT
rescue
def might_raise
raise 'shiping exceptions!'
end
begin
might_raise
rescue
puts 'I was rescued'
end
ensure
def might_raise
raise 'shiping exceptions!'
end
begin
might_raise
rescue
puts 'I was rescued'
ensure
puts 'And I was able to cleanup'
end
twitter.com/_aaronackerman_
github.com/aackerman