Instantly share code, notes, and snippets.

@jah2488 /namespace.rb Secret
Last active Aug 29, 2015

Embed
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, to_const(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 to_const(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
@jah2488

This comment has been minimized.

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

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