Skip to content

Commit cee199b

Browse files
committed
Add wildcard_url validation to page model
To ease the complexity of the page_finder it is required, that the parameter key is unique for all page layouts. This requirement is reducing the searching complexity and also prevent edge cases where different page_layouts in the same tree can have multiple times the same parameter name (e.g. :id). ^ Conflicts: ^ spec/models/alchemy/page_spec.rb
1 parent 3959182 commit cee199b

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

app/models/alchemy/page/page_naming.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module PageNaming
2020
validates :urlname,
2121
uniqueness: {scope: [:language_id, :layoutpage], if: -> { urlname.present? }, case_sensitive: false},
2222
exclusion: {in: RESERVED_URLNAMES}
23+
validate :unique_wildcard_param_keys, if: :has_wildcard_url?
2324

2425
after_update :update_descendants_urlnames,
2526
if: :saved_change_to_urlname?
@@ -55,6 +56,23 @@ def has_wildcard_url?
5556

5657
private
5758

59+
def unique_wildcard_param_keys
60+
wildcard_url.param_keys.each do |key|
61+
conflicting = PageDefinition.all.find do |other|
62+
other.name != page_layout && other.wildcard_url&.param_keys&.include?(key)
63+
end
64+
65+
if conflicting
66+
errors.add(
67+
:page_layout,
68+
:conflicting_wildcard_param_key,
69+
param_key: key,
70+
conflicting_layout: conflicting.name
71+
)
72+
end
73+
end
74+
end
75+
5876
def update_descendants_urlnames
5977
reload
6078
descendants.each(&:update_urlname!)

config/locales/alchemy.en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ en:
834834
base:
835835
restrict_dependent_destroy:
836836
has_many: "There are still %{record} attached to this page. Please remove them first."
837+
page_layout:
838+
conflicting_wildcard_param_key: "has a conflicting wildcard param key \":%{param_key}\" already used by the \"%{conflicting_layout}\" page layout"
837839
descendants:
838840
still_attached_to_nodes: "The following descendant pages are still attached to menu nodes: %{page_names}. Please remove them first."
839841
alchemy/element:

spec/models/alchemy/page_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,39 @@ module Alchemy
18951895
expect(child.urlname).to eq("products/:id/comments")
18961896
end
18971897
end
1898+
1899+
end
1900+
1901+
context "with conflicting wildcard param keys across layouts" do
1902+
let(:parent) { create(:alchemy_page, name: "Items") }
1903+
1904+
before do
1905+
PageDefinition.add(
1906+
name: "conflicting_layout",
1907+
wildcard_url: ":id"
1908+
)
1909+
end
1910+
1911+
after { PageDefinition.reset! }
1912+
1913+
it "is invalid when another layout already uses the same param key" do
1914+
page = build(:alchemy_page, parent: parent, name: "Item", page_layout: "conflicting_layout")
1915+
expect(page).not_to be_valid
1916+
expect(page.errors[:page_layout]).to include(
1917+
a_string_matching(/param key ":id".*"product_detail"/)
1918+
)
1919+
end
1920+
end
1921+
1922+
context "with the same wildcard layout under different parents" do
1923+
let(:parent_a) { create(:alchemy_page, name: "Section A") }
1924+
let(:parent_b) { create(:alchemy_page, name: "Section B") }
1925+
1926+
it "allows creating pages with the same layout" do
1927+
create(:alchemy_page, parent: parent_a, name: "Detail A", page_layout: "product_detail")
1928+
page_b = build(:alchemy_page, parent: parent_b, name: "Detail B", page_layout: "product_detail")
1929+
expect(page_b).to be_valid
1930+
end
18981931
end
18991932

19001933
context "if new urlname exists as a legacy url" do

0 commit comments

Comments
 (0)