Skip to content

Commit 2e15010

Browse files
committed
Delegate ActionText::Content#deconstruct to Nokogiri
Since `ActionText::Content` wraps an `ActionText::Fragment`, and `ActionText::Fragment` wraps a `Nokogiri::XML::DocumentFragment`, then `ActionText::Content` should be able to rely on the newer Ruby pattern matching introduced by [[email protected]][] (mainly the [DocumentFragment#deconstruct][] method): ```ruby content = ActionText::Content.new <<~HTML <h1>Hello, world</h1> <div>The body</div> HTML content => [h1, div] assert_pattern { h1 => { content: "Hello, world" } } assert_pattern { div => { content: "The body" } } ``` The implementation change relies on delegating from `Content` to `Fragment`, and from `Fragment` to `DocumentFragment#elements` (to deliberately exclude text nodes). [[email protected]]: https://nokogiri.org/CHANGELOG.html?h=pattern [DocumentFragment#deconstruct]: https://nokogiri.org/rdoc/Nokogiri/XML/DocumentFragment.html?h=deconstruct#method-i-deconstruct
1 parent 354d1c4 commit 2e15010

File tree

6 files changed

+44
-0
lines changed

6 files changed

+44
-0
lines changed

actiontext/CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
* Delegate `ActionText::Content#deconstruct` to `Nokogiri::XML::DocumentFragment#elements`
2+
3+
```ruby
4+
content = ActionText::Content.new <<~HTML
5+
<h1>Hello, world</h1>
6+
7+
<div>The body</div>
8+
HTML
9+
10+
content => [h1, div]
11+
12+
assert_pattern { h1 => { content: "Hello, world" } }
13+
assert_pattern { div => { content: "The body" } }
14+
```
15+
16+
*Sean Doyle*
17+
118
* Fix all Action Text database related models to respect
219
`ActiveRecord::Base.table_name_prefix` configuration.
320

actiontext/lib/action_text/content.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Content
2424

2525
attr_reader :fragment
2626

27+
delegate :deconstruct, to: :fragment
2728
delegate :blank?, :empty?, :html_safe, :present?, to: :to_html # Delegating to to_html to avoid including the layout
2829

2930
class << self

actiontext/lib/action_text/fragment.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ def from_html(html)
2121

2222
attr_reader :source
2323

24+
delegate :deconstruct, to: "source.elements"
25+
2426
def initialize(source)
2527
@source = source
2628
end

actiontext/test/unit/content_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,7 @@ def with_attachment_tag_name(tag_name)
210210
ActionText::Attachment.tag_name = previous_tag_name
211211
end
212212
end
213+
214+
if RUBY_VERSION >= "3.1"
215+
require_relative "./content_test/pattern_matching_test_cases"
216+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
class ActionText::PatternMatchingTestCases < ActiveSupport::TestCase
4+
test "delegates pattern matching to Nokogiri" do
5+
content = ActionText::Content.new <<~HTML
6+
<h1 id="hello-world">Hello, world</h1>
7+
8+
<div>The body</div>
9+
HTML
10+
11+
# rubocop:disable Lint/Syntax
12+
content => [h1, div]
13+
14+
assert_pattern { h1 => { name: "h1", content: "Hello, world", attributes: [{ name: "id", value: "hello-world" }] } }
15+
refute_pattern { h1 => { name: "h1", content: "Goodbye, world" } }
16+
assert_pattern { div => { content: "The body" } }
17+
# rubocop:enable Lint/Syntax
18+
end
19+
end

actionview/test/template/test_case_test/pattern_matching_test_cases.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ActionView::PatternMatchingTestCases < ActionView::TestCase
99
# rubocop:disable Lint/Syntax
1010
assert_pattern { document_root_element.at("h1") => { content: "Eloy", attributes: [{ name: "id", value: "name" }] } }
1111
refute_pattern { document_root_element.at("h1") => { content: "Not Eloy" } }
12+
# rubocop:enable Lint/Syntax
1213
end
1314

1415
test "rendered.html integrates with pattern matching" do

0 commit comments

Comments
 (0)