Skip to content

Instantly share code, notes, and snippets.

@jah2488
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jah2488/8938747 to your computer and use it in GitHub Desktop.
Save jah2488/8938747 to your computer and use it in GitHub Desktop.
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
@jah2488
Copy link
Author

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

@jah2488
Copy link
Author

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