# Help me understand this technique from an open source app?

**URL:** <https://www.ruby-forum.com/t/help-me-understand-this-technique-from-an-open-source-app/158541>\
**Category:** Ruby\
**Created:** [January 24, 2009, 3:10pm UTC](https://www.ruby-forum.com/t/help-me-understand-this-technique-from-an-open-source-app/158541 "2009-01-24T15:10:02Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pitosalas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a4c791/32.png) [@pitosalas](https://www.ruby-forum.com/u/pitosalas)\
**Post date:** [January 24, 2009, 3:10pm UTC](https://www.ruby-forum.com/t/help-me-understand-this-technique-from-an-open-source-app/158541/1 "2009-01-24T15:10:02Z")

</div>

n the code at the bottom (from HTTParty), the module is included in  
some other class (“O”), and among the effects is that (for example)  
the method default\_params becomes available in “O”. I don’t understand  
the technique. Given that the module is used as a mixin, then if I  
wanted to have that method, I could just define it under module  
HTTParty with a normal def. Moreover, the following doesn’t work:

class Parent  
include HTTParty

def my\_method  
default\_params :x =\> “X”  
end  
end

class Child \< Parent  
def other  
my\_method  
end  
end

There’s some sophisticated meta programming going on. Any help  
understanding it would be greatly appreciated!

Pito

=============from HTTParty==============  
module HTTParty  
AllowedFormats = {:xml =\> ‘text/xml’, :json =\> ‘application/json’,  
:html =\> ‘text/html’}

def self.included(base)  
base.extend ClassMethods  
base.send :include, ModuleLevelInheritableAttributes  
base.send(:mattr\_inheritable, :default\_options)  
base.instance\_variable\_set("@default\_options", {})  
end

module ClassMethods  
def default\_options  
@default\_options  
end

def http\_proxy(addr=nil, port = nil)  
default\_options[:http\_proxyaddr] = addr  
default\_options[:http\_proxyport] = port  
end

def base\_uri(uri=nil)  
return default\_options[:base\_uri] unless uri  
default\_options[:base\_uri] = HTTParty.normalize\_base\_uri(uri)  
end

def basic\_auth(u, p)  
default\_options[:basic\_auth] = {:username =\> u, :password =\> p}  
end

def default\_params(h={})  
raise ArgumentError, ‘Default params must be a hash’ unless  
h.is\_a?(Hash)  
default\_options[:default\_params] ||= {}  
default\_options[:default\_params].merge!(h)  
end

def headers(h={})  
raise ArgumentError, ‘Headers must be a hash’ unless h.is\_a?  
(Hash)  
default\_options[:headers] ||= {}  
default\_options[:headers].merge!(h)  
end

def format(f)  
raise UnsupportedFormat, “Must be one of:  
#{AllowedFormats.keys.join(’, ')}” unless AllowedFormats.key?(f)  
default\_options[:format] = f  
end

def get(path, options={})  
perform\_request Net::HTTP::Get, path, options  
end

def post(path, options={})  
perform\_request Net::HTTP::Post, path, options  
end

def put(path, options={})  
perform\_request Net::HTTP::Put, path, options  
end

def delete(path, options={})  
perform\_request Net::HTTP::Delete, path, options  
end

private  
def perform\_request(http\_method, path, options) #:nodoc:  
Request.new(http\_method, path,  
default\_options.dup.merge(options)).perform  
end  
end

---

<div class="post-metadata">

**Author:** ![pitosalas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a4c791/32.png) [@pitosalas](https://www.ruby-forum.com/u/pitosalas)\
**Post date:** [January 25, 2009, 4:43pm UTC](https://www.ruby-forum.com/t/help-me-understand-this-technique-from-an-open-source-app/158541/2 "2009-01-25T16:43:22Z")

</div>

Pito S. wrote:

> n the code at the bottom (from HTTParty), the module is included in  
> some other class (“O”), and among the effects is that (for example)  
> the method default\_params becomes available in “O”.

Well, consider this first:

module ClassMethods  
def foo  
puts “hello from class”  
end  
end

module InstanceMethods  
def bar  
puts “hello from instance”  
end  
end

class Parent  
include InstanceMethods  
extend ClassMethods  
end

Parent.foo  
Parent.new.bar

However this pattern is very common, so it’s refactored in two ways.

1. put the module containing class methods _inside_ the module  
containing the instance methods

module MyTools  
… instance methods go here

module ClassMethods  
… class methods go here  
end  
end

1. use the “included” hook so that when you include MyTools, it  
automatically does extend MyTools::ClassMethods at the same time.

The example above becomes:

module MyTools  
def self.included(base)  
base.extend ClassMethods  
end

module ClassMethods  
def foo  
puts “hello from class”  
end  
end

def bar  
puts “hello from instance”  
end  
end

class Parent  
include MyTools  
end

Parent.foo  
Parent.new.bar

At least, I _think_ that’s what you were asking about. There’s also the  
ModuleLevelInheritableAttributes there, but you didn’t post all the code  
for that. But notice that the include hook is calling

mattr\_inheritable :default\_options

in the base class, and also setting a class instance variable.

HTH,

Brian.
