Skip to content

Commit

Permalink
allow dom_id method to accept an array of records_or_classes
Browse files Browse the repository at this point in the history
ref: https://discuss.rubyonrails.org/t/allow-dom-id-method-to-accept-multiple-ids-models/84408

If the first argument (records_or_classes) is an array, this change will loop
through each value and form a singular dom id, then join the parts together.

This change will allow turbo frame tags to accept multiple models (similar to
the `cache` helper from ActionView).

```
<%= turbo_frame_tag [customer, field] do %>
  <!-- code -->
<% end %>
```

See also: hotwired/turbo-rails#476
  • Loading branch information
Justin Wilson committed Jan 8, 2024
1 parent 4470ad7 commit 6ea12c3
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
6 changes: 6 additions & 0 deletions actionview/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
* allow dom_id method to accept an array of records_or_classes

Works similarly to `cache` helper from ActionView.

*Justin Wilson*

* Add the `nonce: true` option for `stylesheet_link_tag` helper to support automatic nonce generation for Content Security Policy.
Works the same way as `javascript_include_tag nonce: true` does.

Expand Down
23 changes: 19 additions & 4 deletions actionview/lib/action_view/record_identifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,25 @@ def dom_class(record_or_class, prefix = nil)
#
# dom_id(Post.find(45), :edit) # => "edit_post_45"
# dom_id(Post, :custom) # => "custom_post"
def dom_id(record_or_class, prefix = nil)
raise ArgumentError, "dom_id must be passed a record_or_class as the first argument, you passed #{record_or_class.inspect}" unless record_or_class
#
# Providing an array of records or classes will join the singular dom_ids together
#
# dom_id([Author.find(20), Post.find(45)]) # => "author_20_post_45"
# dom_id([Author.find(20), Post.find(45)], :dashboard) # => "dashboard_author_20_post_45"
def dom_id(records_or_classes, prefix = nil)
raise ArgumentError, "dom_id must be passed records_or_classes as the first argument, you passed #{records_or_classes.inspect}" unless records_or_classes

if records_or_classes.is_a?(Array)
parts = records_or_classes.map { |object| singular_dom_id(object) }
([prefix] + parts).compact.join(JOIN)
else
singular_dom_id(records_or_classes, prefix)
end
end

private
# Returns a string representation of a single record or class
def singular_dom_id(record_or_class, prefix = nil)
record_id = record_key_for_dom_id(record_or_class) unless record_or_class.is_a?(Class)
if record_id
"#{dom_class(record_or_class, prefix)}#{JOIN}#{record_id}"
Expand All @@ -101,7 +117,6 @@ def dom_id(record_or_class, prefix = nil)
end
end

private
# Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id.
# This can be overwritten to customize the default generated string representation if desired.
# If you need to read back a key from a dom_id in order to query for the underlying database record,
Expand All @@ -112,7 +127,7 @@ def dom_id(record_or_class, prefix = nil)
# make sure yourself that your dom ids are valid, in case you override this method.
def record_key_for_dom_id(record) # :doc:
key = convert_to_model(record).to_key
key && key.all? ? key.join(JOIN) : nil
(key && key.all?) ? key.join(JOIN) : nil
end
end
end
14 changes: 14 additions & 0 deletions actionview/test/template/record_identifier_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ def test_dom_id_with_saved_record
assert_equal "#{@singular}_1", dom_id(@record)
end

def test_dom_id_with_two_saved_records
@record.save
@second_record = Tag.new
@second_record.save
assert_equal "#{@singular}_1_tag_1", dom_id([@record, @second_record])
end

def test_dom_id_with_two_saved_records_and_prefix
@record.save
@second_record = Tag.new
@second_record.save
assert_equal "my_prefix_#{@singular}_1_tag_1", dom_id([@record, @second_record], "my_prefix")
end

def test_dom_id_with_composite_primary_key_record
record = Cpk::Book.new(id: [1, 123])
assert_equal("cpk_book_1_123", dom_id(record))
Expand Down

0 comments on commit 6ea12c3

Please sign in to comment.