Support `has_rich_text` with `strict_loading:`

Expand the `has_rich_text` signature to accept a `strict_loading:`
value. Forward that value along to the `has_one` declaration made under
the hood. When omitted, `strict_loading:` will be set to the value of
the `strict_loading_by_default` class attribute (false by default).
This commit is contained in:
Sean Doyle 2022-10-18 17:01:57 -04:00
parent cf2be23577
commit 4a743b9e0a
3 changed files with 52 additions and 2 deletions

View File

@ -1,3 +1,7 @@
* Support `strict_loading:` option for `has_rich_text` declaration
*Sean Doyle*
* Update ContentAttachment so that it can encapsulate arbitrary HTML content in a document. * Update ContentAttachment so that it can encapsulate arbitrary HTML content in a document.
*Jamis Buck* *Jamis Buck*

View File

@ -30,7 +30,11 @@ module ActionText
# #
# * <tt>:encrypted</tt> - Pass true to encrypt the rich text attribute. The encryption will be non-deterministic. See # * <tt>:encrypted</tt> - Pass true to encrypt the rich text attribute. The encryption will be non-deterministic. See
# +ActiveRecord::Encryption::EncryptableRecord.encrypts+. Default: false. # +ActiveRecord::Encryption::EncryptableRecord.encrypts+. Default: false.
def has_rich_text(name, encrypted: false) #
# * <tt>:strict_loading</tt> - Pass true to force strict loading. When
# omitted, <tt>strict_loading:</tt> will be set to the value of the
# <tt>strict_loading_by_default</tt> class attribute (false by default).
def has_rich_text(name, encrypted: false, strict_loading: strict_loading_by_default)
class_eval <<-CODE, __FILE__, __LINE__ + 1 class_eval <<-CODE, __FILE__, __LINE__ + 1
def #{name} def #{name}
rich_text_#{name} || build_rich_text_#{name} rich_text_#{name} || build_rich_text_#{name}
@ -47,7 +51,8 @@ module ActionText
rich_text_class_name = encrypted ? "ActionText::EncryptedRichText" : "ActionText::RichText" rich_text_class_name = encrypted ? "ActionText::EncryptedRichText" : "ActionText::RichText"
has_one :"rich_text_#{name}", -> { where(name: name) }, has_one :"rich_text_#{name}", -> { where(name: name) },
class_name: rich_text_class_name, as: :record, inverse_of: :record, autosave: true, dependent: :destroy class_name: rich_text_class_name, as: :record, inverse_of: :record, autosave: true, dependent: :destroy,
strict_loading: strict_loading
scope :"with_rich_text_#{name}", -> { includes("rich_text_#{name}") } scope :"with_rich_text_#{name}", -> { includes("rich_text_#{name}") }
scope :"with_rich_text_#{name}_and_embeds", -> { includes("rich_text_#{name}": { embeds_attachments: :blob }) } scope :"with_rich_text_#{name}_and_embeds", -> { includes("rich_text_#{name}": { embeds_attachments: :blob }) }

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
require "test_helper"
class ActionText::StrictLoadingTest < ActiveSupport::TestCase
class MessageWithStrictLoading < Message
self.strict_loading_by_default = true
has_rich_text :strict_loading_content
end
class MessageWithFooter < MessageWithStrictLoading
has_rich_text :footer, strict_loading: false
end
test "has_rich_text reads strict_loading: option from strict_loading_by_default" do
MessageWithStrictLoading.create! strict_loading_content: "ignored"
assert_raises ActiveRecord::StrictLoadingViolationError do
MessageWithStrictLoading.all.map(&:strict_loading_content)
end
MessageWithStrictLoading.with_rich_text_strict_loading_content.map(&:strict_loading_content)
end
test "pre-loading the association does not raise a StrictLoadingViolationError" do
MessageWithStrictLoading.create! strict_loading_content: "ignored"
records = MessageWithStrictLoading.with_rich_text_strict_loading_content.all
records.map(&:strict_loading_content)
end
test "has_rich_text accepts strict_loading: overrides" do
MessageWithFooter.create! footer: "ignored"
records = MessageWithFooter.all
records.map(&:footer)
end
end