Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method to get Array of given nodes and their ancestors except these in options #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions lib/acts_as_sane_tree/singleton_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,40 @@ def root
end
end

# nodes:: Array of node ids
# options:: Hash with except key and value of node id/ids
# Return Array of given nodes and their ancestors except these in options
def ancestors_with_nodes(nodes, options={})
table_name = configuration[:class].table_name
query_select_string = "DISTINCT #{table_name}.*"
query_string = <<-SQL
(WITH RECURSIVE crumbs AS (
SELECT #{table_name}.*
FROM #{table_name}
WHERE id IN (?)
UNION ALL
SELECT alias1.*
FROM crumbs
JOIN #{table_name} alias1 ON alias1.id = crumbs.parent_id
) SELECT * FROM crumbs) as #{table_name}
SQL
sanitize_query_string = ActiveRecord::Base.send(:sanitize_sql_array, [query_string, Array(nodes)])

if options[:except]
aditional_query_string = <<-SQL
WHERE #{table_name}.id NOT IN (?)
SQL
sanitize_aditional_query_string = ActiveRecord::Base.send(:sanitize_sql_array, [aditional_query_string, Array(options[:except])])
sanitize_query_string += sanitize_aditional_query_string
end

if(rails_arel?)
configuration[:class].select(query_select_string).from(sanitize_query_string)
else
configuration[:class].scoped(select: query_select_string, from: sanitize_query_string)
end
end

# src:: Array of nodes
# chk:: Array of nodes
# Return true if any nodes within chk are found within src
Expand Down
14 changes: 14 additions & 0 deletions spec/acts_as_sane_tree_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@
end

describe "when using an acts_as_sane_tree class" do
before do
@root_0 = Node.find_by(name: :root_0)
@root_1 = Node.find_by(name: :root_1)
@node_0_10 = Node.find_by(name: :node_0_10)
@node_1_5 = Node.find_by(name: :node_1_5)
end
it "should provide all roots" do
if(AREL)
assert_equal Node.where(:parent_id => nil).count, Node.roots.count
Expand All @@ -207,6 +213,14 @@
assert_kind_of Node, Node.root
assert Node.root.parent_id.nil?, 'Expecting root node to have no parent'
end
it "should provide nodes with all ancestors" do
assert_equal Node.find(4).ancestors.count + 1, Node.ancestors_with_nodes(4).length
assert_equal @node_0_10.ancestors.count + @node_1_5.ancestors.count + 2, Node.ancestors_with_nodes([@node_0_10.id, @node_1_5.id]).length
end
it "should provide nodes with all ancestors except given in options" do
assert_equal Node.find(4).ancestors.count, Node.ancestors_with_nodes(4, {except: 4}).length
assert_equal @node_0_10.ancestors.count + @node_1_5.ancestors.count, Node.ancestors_with_nodes([@node_0_10.id, @node_1_5.id], {except: [@root_0.id, @root_1.id]}).length
end
describe "when checking for nodes within other node descendants" do
before do
@root = Node.root
Expand Down