Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
breadcrumb.rb
class String
def underscore
self.scan(/[A-Z][a-z]+/).map { |name| name.tr('A-Z', 'a-z') }.join("_")
end
end
class Crumb
def initialize(mgr, &block)
@mgr = mgr
@block = block
end
def link(url, name)
@link ||= "<a href='#{url}'>#{name}</a>"
end
def parent(obj)
@parent ||= obj
end
def render(obj)
instance_exec obj, &@block
return [] if @parent.nil?
[@link] + @mgr.render(@parent)
end
end
class CrumbManager
def initialize(&block)
@crumbs = {}
instance_eval(&block)
end
def crumb(key, &block)
@crumbs[key] = Crumb.new(self, &block)
end
def lookup_key(obj)
obj.is_a?(Symbol) ? obj : obj.class.to_s.underscore.to_sym
end
def lookup(obj)
@crumbs[lookup_key(obj)]
end
def render(obj)
(lookup(obj) || fail).render(obj)
end
def breadcrumb(obj)
render(obj).reverse.join(" > ")
end
end
Product = Struct.new(:name, :id, :category, keyword_init: true)
Category = Struct.new(:name, :id, keyword_init: true)
def crumbs(&block)
@mgr = CrumbManager.new(&block)
end
def breadcrumb(obj)
@mgr&.breadcrumb(obj)
end
crumbs do
crumb :home do
link "Home", "https://google.co.jp/"
end
crumb :category do |category|
link category.name, "https://example.com/categories/#{category.id}"
parent :home
end
crumb :product do |product|
link product.name, "https://example.com/products/#{product.id}"
parent product.category
end
end
product = Product.new(name: 'トヨタカローラ', id: 1, category: Category.new(name: '車', id: 2))
puts breadcrumb(product)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.