Skip to content

Commit

Permalink
fix(available_element_definitions): Do not mutate element_definitions
Browse files Browse the repository at this point in the history
`Page#available_element_definitions` returns elements still available
for that page. Taking unique and limited elements into account.

`Page#element_definitions` always returns the collections of defined
elements, not matter of they have been used or not.

Due to referencing the same instance variable and in memory object
`available_element_definitions` was mutating the `element_definitions`
object.
  • Loading branch information
tvdeyen committed Apr 30, 2024
1 parent 1e59d50 commit da519a0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
16 changes: 8 additions & 8 deletions app/models/alchemy/page/page_elements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,21 @@ def duplicate_elements(elements, repository, page_version)
# type: Richtext
#
def available_element_definitions(only_element_named = nil)
@_element_definitions ||= if only_element_named
@_available_element_definitions ||= if only_element_named
definition = Element.definition_by_name(only_element_named)
element_definitions_by_name(definition["nestable_elements"])
else
element_definitions
element_definitions.dup
end

return [] if @_element_definitions.blank?
return [] if @_available_element_definitions.blank?

existing_elements = draft_version.elements.not_nested
@_existing_element_names = existing_elements.pluck(:name)
delete_unique_element_definitions!
delete_outnumbered_element_definitions!

@_element_definitions
@_available_element_definitions
end

# All names of elements that can actually be placed on current page.
Expand Down Expand Up @@ -186,18 +186,18 @@ def generate_elements
end
end

# Deletes unique and already present definitions from @_element_definitions.
# Deletes unique and already present definitions from @_available_element_definitions.
#
def delete_unique_element_definitions!
@_element_definitions.delete_if do |element|
@_available_element_definitions.delete_if do |element|
element["unique"] && @_existing_element_names.include?(element["name"])
end
end

# Deletes limited and outnumbered definitions from @_element_definitions.
# Deletes limited and outnumbered definitions from @_available_element_definitions.
#
def delete_outnumbered_element_definitions!
@_element_definitions.delete_if do |element|
@_available_element_definitions.delete_if do |element|
outnumbered = @_existing_element_names.select { |name| name == element["name"] }
element["amount"] && outnumbered.count >= element["amount"].to_i
end
Expand Down
12 changes: 12 additions & 0 deletions spec/models/alchemy/page_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,12 @@ module Alchemy
expect(subject.collect { |e| e["name"] }).to include("article")
expect(subject.collect { |e| e["name"] }).not_to include("header")
end

it "does not mutate the element_definitions collection" do
expect(page.element_definitions.collect { |e| e["name"] }).to include("header")
subject
expect(page.element_definitions.collect { |e| e["name"] }).to include("header")
end
end

context "limited amount" do
Expand Down Expand Up @@ -650,6 +656,12 @@ module Alchemy
it "should be ignored if unique" do
expect(subject.collect { |e| e["name"] }).not_to include("unique_headline")
end

it "does not mutate the element_definitions collection" do
expect(page.element_definitions.collect { |e| e["name"] }).to include("column_headline")
subject
expect(page.element_definitions.collect { |e| e["name"] }).to include("column_headline")
end
end

describe ".ransackable_scopes" do
Expand Down

0 comments on commit da519a0

Please sign in to comment.