Skip to content

Instantly share code, notes, and snippets.

@douglaslise
Last active January 4, 2016 13:21
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 douglaslise/66c466a652bd7ff7ddf3 to your computer and use it in GitHub Desktop.
Save douglaslise/66c466a652bd7ff7ddf3 to your computer and use it in GitHub Desktop.
DSL Menus Wonder
# A chamada deve ser feita usando o método "menu"
# O primeiro argumento é o ID
# O segundo, opcional, é o LABEL
# Ainda podem ser passadas as options em formato de hash.
# Por exemplo o path, quando este não depender de objeto (index ou new). Quando depender de objeto deve-se usar bloco)
# Após pode ser passado um bloco que pode conter:
# Chamadas aos menus filhos deste
# Chamada ao método "label", passando um bloco, que deve retornar o label para este nível de menu
# Chamada ao método "path", passando um bloco, que deve retornar o path para este nível de menu
# Chamada ao método "parent", passando um bloco, que deve retornar o objeto que deve ser
# utilizado para obter label e path em níveis superiores ao atual
m = Menu.new do
menu :oport, "Oportunidades" do
menu :oport_cadastros, "Cadastros" do
menu :oport_oportunidades, "Oportunidades", path: "cml_motivos_estagios_oportunidade" do
menu :show do
label &:to_s #label {|oportunidade| oportunidade.to_s }
path {|oportunidade|
oportunidade.url #cml_oportunidade_path(oportunidade)
}
menu :oport_edicao, "Edição" do
path {|oport| edit_cml_oportunidade_path(oport)}
end
menu :itens_oportunidade, "Itens" do
menu :item_oportunidade do
label {|item| item.to_s }
parent {|item| item.oportunidade }
parent &:oportunidade
end
end
end
end
menu :oport_estagios, "Estágios", path: "cml_motivos_estagios_oportunidade" do
end
end
end
end
class Oportunidade
def to_s
"Oportunidade 1"
end
def url
"/cml/oportunidades/5"
end
end
class ItemOportunidade
attr_accessor :oportunidade
def to_s
"Instância de item da oportunidade #{oportunidade}"
end
end
o = Oportunidade.new
i = ItemOportunidade.new
i.oportunidade = o
puts m.breadcrumb_for :item_oportunidade, i
puts "*"*50
puts m.breadcrumb_for :oport_edicao, o
puts "*"*50
puts m.menu_tree max_depth: 3
{:label=>"Início", :path=>nil}
{:label=>"Oportunidades", :path=>nil}
{:label=>"Cadastros", :path=>nil}
{:label=>"Oportunidades", :path=>"cml_motivos_estagios_oportunidade"}
{:label=>"Oportunidade 1", :path=>"/cml/oportunidades/5"}
{:label=>"Itens", :path=>nil}
{:label=>"Instância de item da oportunidade Oportunidade 1", :path=>nil}
**************************************************
{:label=>"Início", :path=>nil}
{:label=>"Oportunidades", :path=>nil}
{:label=>"Cadastros", :path=>nil}
{:label=>"Oportunidades", :path=>"cml_motivos_estagios_oportunidade"}
{:label=>"Oportunidade 1", :path=>"/cml/oportunidades/5"}
{:label=>"Edição", :path=>"edit_/cml/oportunidades/5"}
**************************************************
{:id=>:root,
:label=>"Início",
:path=>nil,
:subitems=>
[{:id=>:oport,
:label=>"Oportunidades",
:path=>nil,
:subitems=>
[{:id=>:oport_cadastros,
:label=>"Cadastros",
:path=>nil,
:subitems=>
[{:id=>:oport_oportunidades, :label=>"Oportunidades", :path=>"cml_motivos_estagios_oportunidade"},
{:id=>:oport_estagios, :label=>"Estágios", :path=>"cml_motivos_estagios_oportunidade"}]}]}]}
class Menu
attr_reader :items
def initialize(&block)
@items = {}
items[:root] = MenuItem.new(self, 0, :root, "Início")
items[:root].instance_eval(&block)
end
def breadcrumb_for(id, object = nil)
items[id].breadcrumbs(object)
end
def menu_tree(options = {})
active = options[:active]
max_depth = options[:max_depth]
items[:root].tree(active, max_depth)
end
end
class MenuItem
attr_accessor :menu_instance, :level, :id, :label_text, :label_proc, :path_fixed, :path_proc, :block, :parent_item, :parent_block, :subitems
def initialize(menu_instance, level, id, label = nil, options = {}, &block)
if label.is_a?(Hash)
options = label
label = options.delete(:label)
end
@level = level
@menu_instance = menu_instance
@id = id
@label_text = label
@path_fixed = options[:path]
@block = block
@subitems = []
end
def menu(id, label = nil, options = {}, &block)
sub_item = MenuItem.new(menu_instance, level + 1, id, label, options, &block)
menu_instance.items[id] = sub_item
sub_item.parent_item = self
if block_given?
#sub_item.instance_eval(&block)# yield
sub_item.instance_exec(&block)
raise "MenuItem #{id} sem label definido" unless sub_item.label_proc || sub_item.label_text
end
end
def breadcrumbs(object = nil)
result = []
if parent_item
if parent_block
parent_object = parent_block.call(object)
else
parent_object = object
end
result += parent_item.breadcrumbs(parent_object)
end
current = {}
current[:label] = resolve_label(object)
current[:path] = resolve_path(object)
result << current
end
def tree(active, max_depth)
result = {
id: id,
label: resolve_label(nil),
path: resolve_path(nil)
}
puts "max_depth: #{max_depth}"
if !max_depth || level < max_depth
result[:subitems] = subitems.collect do |sub_item|
sub_item.tree(active, max_depth)
end
end
result
end
def parent_item=(parent_item)
if parent_item
@parent_item = parent_item
parent_item.subitems << self
else
@parent_item.subitems.delete(self)
@parent_item = nil
end
end
private
def label(&block)
@label_proc = block
end
def path(&block)
@path_proc = block
end
def parent(&block)
@parent_block = block
end
def resolve_label(object)
label_text || label_proc.call(object)
end
def resolve_path(object)
if path_fixed
path_fixed
elsif path_proc && object
path_proc.call(object)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment