Skip to content

Commit a320457

Browse files
committed
Add wildcard url type
Add an active record type for wildcard urls. These types will be later used in the page definition and can a simple string or hash with a pattern attribute and an optional params attribute. This way the user can configure the wildcard for a page layout and it will be validated when Alchemy reads in the page layout.
1 parent 74f33f3 commit a320457

2 files changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
module Alchemy
4+
class WildcardUrlType < ActiveModel::Type::Value
5+
class Value
6+
attr_reader :pattern, :params
7+
8+
def initialize(pattern:, params: {})
9+
@pattern = pattern
10+
@params = params
11+
end
12+
13+
def present?
14+
pattern.present?
15+
end
16+
end
17+
18+
def cast(value)
19+
case value
20+
when nil then nil
21+
when String
22+
Value.new(pattern: value)
23+
when Hash
24+
attrs = value.symbolize_keys
25+
Value.new(
26+
pattern: attrs[:pattern],
27+
params: attrs[:params] || {}
28+
)
29+
else
30+
value
31+
end
32+
end
33+
34+
def assert_valid_value(value)
35+
return if value.nil?
36+
37+
unless value.is_a?(String) || value.is_a?(Hash)
38+
raise ArgumentError, "#{value.inspect} is not a valid wildcard_url. Must be a String or Hash."
39+
end
40+
41+
if value.is_a?(Hash)
42+
attrs = value.symbolize_keys
43+
unless attrs[:pattern].is_a?(String)
44+
raise ArgumentError, "wildcard_url hash must include a \"pattern\" key with a String value."
45+
end
46+
end
47+
end
48+
end
49+
end
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# frozen_string_literal: true
2+
3+
require "rails_helper"
4+
5+
module Alchemy
6+
RSpec.describe WildcardUrlType do
7+
subject(:type) { described_class.new }
8+
9+
describe "#cast" do
10+
context "with nil" do
11+
it "returns nil" do
12+
expect(type.cast(nil)).to be_nil
13+
end
14+
end
15+
16+
context "with a String" do
17+
let(:result) { type.cast(":slug") }
18+
19+
it "sets the pattern" do
20+
expect(result.pattern).to eq(":slug")
21+
end
22+
23+
it "defaults params to empty hash" do
24+
expect(result.params).to eq({})
25+
end
26+
end
27+
28+
context "with a Hash using string keys" do
29+
let(:result) { type.cast({"pattern" => ":id", "params" => {"id" => "integer"}}) }
30+
31+
it "sets the pattern" do
32+
expect(result.pattern).to eq(":id")
33+
end
34+
35+
it "sets the params" do
36+
expect(result.params).to eq({"id" => "integer"})
37+
end
38+
end
39+
40+
context "with a Hash using symbol keys" do
41+
let(:result) { type.cast({pattern: ":year/:slug", params: {year: "integer"}}) }
42+
43+
it "sets the pattern" do
44+
expect(result.pattern).to eq(":year/:slug")
45+
end
46+
47+
it "sets the params" do
48+
expect(result.params).to eq({year: "integer"})
49+
end
50+
end
51+
52+
context "with a Hash without params" do
53+
let(:result) { type.cast({"pattern" => ":slug"}) }
54+
55+
it "defaults params to empty hash" do
56+
expect(result.params).to eq({})
57+
end
58+
end
59+
60+
context "with an unsupported type" do
61+
it "returns the value as-is" do
62+
expect(type.cast(42)).to eq(42)
63+
end
64+
end
65+
end
66+
67+
describe "#assert_valid_value" do
68+
it "accepts nil" do
69+
expect { type.assert_valid_value(nil) }.not_to raise_error
70+
end
71+
72+
it "accepts a String" do
73+
expect { type.assert_valid_value(":slug") }.not_to raise_error
74+
end
75+
76+
it "accepts a Hash with a pattern" do
77+
expect { type.assert_valid_value({"pattern" => ":id"}) }.not_to raise_error
78+
end
79+
80+
it "raises for an unsupported type" do
81+
expect { type.assert_valid_value(42) }.to raise_error(
82+
ArgumentError, /is not a valid wildcard_url/
83+
)
84+
end
85+
86+
it "raises for a Hash without a pattern" do
87+
expect { type.assert_valid_value({"params" => "integer"}) }.to raise_error(
88+
ArgumentError, /must include a "pattern" key/
89+
)
90+
end
91+
92+
it "raises for a Hash with a non-string pattern" do
93+
expect { type.assert_valid_value({"pattern" => 123}) }.to raise_error(
94+
ArgumentError, /must include a "pattern" key/
95+
)
96+
end
97+
end
98+
99+
describe WildcardUrlType::Value do
100+
subject(:value) { described_class.new(pattern: ":id", params: {"id" => "integer"}) }
101+
102+
describe "#present?" do
103+
it "returns true when pattern is present" do
104+
expect(value).to be_present
105+
end
106+
107+
context "when pattern is blank" do
108+
subject(:value) { described_class.new(pattern: "") }
109+
110+
it { is_expected.not_to be_present }
111+
end
112+
113+
context "when pattern is nil" do
114+
subject(:value) { described_class.new(pattern: nil) }
115+
116+
it { is_expected.not_to be_present }
117+
end
118+
end
119+
end
120+
end
121+
end

0 commit comments

Comments
 (0)