Created
March 6, 2015 19:58
-
-
Save bsodmike/4b270175319a5557cd63 to your computer and use it in GitHub Desktop.
Example of recursive tree traversal in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Do note that
current_site.taxons
are of classSiteTaxon
; as this is used as a 'lookup' tree for associations with categories.