Skip to content

Instantly share code, notes, and snippets.

@bsodmike
Created March 6, 2015 19:58
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 bsodmike/4b270175319a5557cd63 to your computer and use it in GitHub Desktop.
Save bsodmike/4b270175319a5557cd63 to your computer and use it in GitHub Desktop.
Example of recursive tree traversal in Ruby
module NDAClient
module Queries
class FindCategoryAndProduct
def initialize(site, user, request, params)
@current_site = site
@current_user = user
@request = request
@params = params
end
attr_reader :current_site, :current_user, :request, :params
def call
taxon = params[:taxon]
segments = params[:segments] || []
segments = segments.split('/')
_segments = segments.clone
category_tree = find_category(taxon, segments)
product = find_product(category_tree, _segments)
[category_tree, product]
end
protected
def find_product(category_tree, segments)
return if category_tree.any? && category_tree.size <= 1 # tree is either empty or only contains the taxon
return if Helpers::NavigationHelper.path_segment_for_category_from(category_tree.last.name) == segments.last
product = nil
product_code = segments.last
category = category_tree.last
fetched_product = category.products.find_by_code(product_code)
return unless fetched_product
product = fetched_product if Product.visible(current_user).map(&:id).include?(fetched_product.id)
product
end
def find_category(taxon_name, segments)
# NOTE
# Rename column as `url_tag` rather than using a virtual attribute?
taxon = current_site.taxons.find_by_category_name(
Helpers::NavigationHelper.category_name_from(taxon_name)
)
return unless taxon
taxon_categories = Category.where('id IN(?)', taxon.children.map(&:id))
[taxon, build_category_tree(taxon_categories, segments, [])].flatten
end
def build_category_tree(collection, segments, output)
attempt = collection
start = Helpers::NavigationHelper.category_name_from(segments.shift)
return output unless Category.find_by_url_tag(start) # check if path segement is a valid Category name
context = collection.find_by_url_tag(start)
output << context if context
unless context
if output.last && output.last.children.any?
attempt = Category.where('id IN(?)', output.last.children.map(&:id))
segments.unshift(start)
end
end
return output if segments.empty?
build_category_tree(attempt, segments, output)
end
end
end
end
@bsodmike
Copy link
Author

bsodmike commented Mar 6, 2015

Do note that current_site.taxons are of class SiteTaxon; as this is used as a 'lookup' tree for associations with categories.

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