Skip to content

Commit 3618f49

Browse files
authored
Merge pull request #3666 from AlchemyCMS/refactor-parent_element_ids
refactor(element): Use folded_parent_element_ids for expanding nested elements
2 parents 9a9488d + 4129581 commit 3618f49

File tree

4 files changed

+42
-16
lines changed

4 files changed

+42
-16
lines changed

app/controllers/alchemy/admin/elements_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def expand
136136
@element.update_columns(folded: false)
137137
# We want to expand the upper most parent first in order to prevent
138138
# re-painting issues in the browser
139-
parent_element_ids = @element.parent_element_ids.reverse
139+
parent_element_ids = @element.folded_parent_element_ids.reverse
140140
Alchemy::Element.where(id: parent_element_ids).update_all(folded: false)
141141

142142
render json: {

app/models/alchemy/element.rb

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,21 @@ def all_from_clipboard_for_parent_element(clipboard, parent_element)
183183
end
184184
end
185185

186-
# Heavily unoptimized naive way to get all parent ids
187-
def parent_element_ids
188-
ids ||= []
189-
parent = parent_element
190-
while parent
191-
ids.push parent.id
192-
parent = parent.parent_element
186+
# Returns IDs of all folded parent elements from immediate parent up to root
187+
#
188+
# Walks up the ancestor chain and collects only the ones that are folded,
189+
# skipping already expanded parents.
190+
#
191+
# @return [Array<Integer>] Folded parent element IDs from immediate parent to root
192+
def folded_parent_element_ids
193+
return [] unless parent_element_id
194+
195+
ids = []
196+
current_id = parent_element_id
197+
while current_id
198+
folded, parent_id = self.class.where(id: current_id).pick(:folded, :parent_element_id)
199+
ids << current_id if folded
200+
current_id = parent_id
193201
end
194202
ids
195203
end

spec/controllers/alchemy/admin/elements_controller_spec.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ module Alchemy
335335

336336
subject { post :expand, params: {id: nested_nested_folded_element.id} }
337337

338-
it "expands all parent elements" do
338+
it "expands all folded parent elements" do
339339
subject
340340
aggregate_failures do
341341
expect(nested_element.reload).to_not be_folded
@@ -345,12 +345,11 @@ module Alchemy
345345
end
346346
end
347347

348-
it "returns json" do
348+
it "returns json with only the folded parent element ids" do
349349
subject
350350
expect(JSON.parse(response.body)).to eq({
351351
"parentElementIds" => [
352352
element.id,
353-
nested_element.id,
354353
nested_nested_element.id,
355354
nested_folded_element.id
356355
],

spec/models/alchemy/element_spec.rb

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -633,15 +633,34 @@ module Alchemy
633633
end
634634
end
635635

636-
describe "#parent_element_ids" do
636+
describe "#folded_parent_element_ids" do
637637
let(:page) { create(:alchemy_page) }
638638

639-
let!(:element1) { create(:alchemy_element, page_version: page.draft_version, name: "slider", autogenerate_nested_elements: false) }
640-
let!(:element2) { create(:alchemy_element, page_version: page.draft_version, name: "slide", parent_element: element1) }
639+
let!(:element1) { create(:alchemy_element, page_version: page.draft_version, name: "slider", folded: true, autogenerate_nested_elements: false) }
640+
let!(:element2) { create(:alchemy_element, page_version: page.draft_version, name: "slide", folded: true, parent_element: element1) }
641641
let!(:element3) { create(:alchemy_element, page_version: page.draft_version, name: "slide", parent_element: element2) }
642642

643-
it "returns parent element ids" do
644-
expect(element3.parent_element_ids).to eq([element2.id, element1.id])
643+
it "returns folded parent element ids from immediate parent to root" do
644+
expect(element3.folded_parent_element_ids).to eq([element2.id, element1.id])
645+
end
646+
647+
it "returns empty array for root element" do
648+
expect(element1.folded_parent_element_ids).to eq([])
649+
end
650+
651+
it "returns single parent for first-level nested element" do
652+
expect(element2.folded_parent_element_ids).to eq([element1.id])
653+
end
654+
655+
it "skips already expanded parents" do
656+
element2.update_columns(folded: false)
657+
expect(element3.folded_parent_element_ids).to eq([element1.id])
658+
end
659+
660+
it "returns empty array when all parents are expanded" do
661+
element1.update_columns(folded: false)
662+
element2.update_columns(folded: false)
663+
expect(element3.folded_parent_element_ids).to eq([])
645664
end
646665
end
647666

0 commit comments

Comments
 (0)