Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A simple ruby method to cleanup nested module setup for namespacing.
def ns(namespace, delim = '.', &block)
nest_mod(namespace.split(delim), block)
end
def nest_mod(mod = Kernel, module_names, block)
return mod.module_exec(&block) if module_names.empty?
find_or_create_constant_in_module(mod, constantize(module_names.first)).tap do |this|
make_module_methods_accessible(this)
this.module_exec do
nest_mod(this, module_names.drop(1), block)
end
end
end
def make_module_methods_accessible(mod)
mod.module_exec { extend self }
end
def find_or_create_constant_in_module(mod, str)
return mod.const_get(str) if mod.const_defined?(str)
return mod.const_set(str, Module.new)
end
def constantize(str)
str.split('_')
.map(&:capitalize)
.join
end
if $0 !~ /rspec/
ns 'my_app.greetings.greeter' do
def present
'hello'
end
end
ns :presenters_greetings do
def present_greeting(greeter)
greeter.present
end
end
puts Presenters::Greetings.present_greeting(MyApp::Greetings::Greeter) #=> 'hello'
else
describe 'namespace' do
context 'ns' do
it 'creates all methods in the nested namespace/module' do
ns 'my_app.dojo.util.options' do
def names
%w(john jill steve carol)
end
end
expect(MyApp::Dojo::Util::Options.names).to eq(%w(john jill steve carol))
end
it 'custom deliminators can optionally be specified' do
ns 'my_app|dojo|util|options', '|' do
def names
%w(john jill steve carol)
end
end
expect(MyApp::Dojo::Util::Options.names).to eq(%w(john jill steve carol))
end
end
context 'nest_mod' do
it 'creates a module given a string and block' do
nest_mod(['greeter'], Proc.new {
@hello = 'hello'
def greet
@hello
end
})
expect(Greeter.greet).to eq('hello')
end
it 'creates nested modules' do
nest_mod(['dojo', 'util', 'options'], Proc.new {
def names
%w(john jill steve carol)
end
})
expect(Dojo::Util::Options.names).to eq(%w(john jill steve carol))
end
end
context 'to_const' do
it 'hello_world -> HelloWorld' do
expect(to_const('hello_world')).to eq('HelloWorld')
end
end
end
end
module Presenters
module Greetings
def present_greeting(greeter)
greeter.present
end
end
end
module MyApp
module Greetings
module Greeter
def present
'hello'
end
end
end
end
#vs
ns 'presenters.greetings' do
def present_greeting(greeter)
greeter.present
end
end
ns 'my_app.greetings.greeter' do
def present
'hello'
end
end
Owner

jah2488 commented Feb 11, 2014

I figured this was easier than publishing a gem, but maybe that should come next. The only limitation I've run into currently is that you lose constant assignment. If you want to assign any constants in the scope of the module you're working in, you will have to use const_set

Owner

jah2488 commented Feb 14, 2014

I originally made this gist private on accident, if you're curious in some of the revisions the code went through, there is some more history in the private gist. https://gist.github.com/jah2488/a9d891d4393d2e5df327

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment