Module: Collavre::Creative::Describable
- Extended by:
- ActiveSupport::Concern
- Included in:
- Collavre::Creative
- Defined in:
- app/models/collavre/creative/describable.rb
Instance Method Summary collapse
-
#attachment_node_html(blob) ⇒ Object
HTML for embedding a blob inline, branching on content type.
-
#attachments_embeddable? ⇒ Boolean
GitHub-synced creatives reject any description change (description_cannot_change_if_github_source), so embedding would raise and orphan the blob.
- #creative_snippet ⇒ Object
-
#effective_description(variation_id = nil, html = true) ⇒ Object
Linked Creative의 description을 안전하게 반환.
-
#embed_attachment_blob!(blob) ⇒ Object
Append an attachment node and save; after_save reconcile attaches the blob to creative.files.
-
#remove_attachment!(signed_id) ⇒ Object
Remove the attachment for ‘signed_id`.
Instance Method Details
#attachment_node_html(blob) ⇒ Object
HTML for embedding a blob inline, branching on content type. The proxy path MUST match what extract_signed_ids_from_description scans and what the sanitizer allows.
68 69 70 71 72 73 74 75 76 77 78 |
# File 'app/models/collavre/creative/describable.rb', line 68 def (blob) url = "/public-assets/blobs/#{blob.signed_id}/#{blob.filename.sanitized}" name = ERB::Util.html_escape(blob.filename.to_s) if blob.content_type.to_s.start_with?("image/") %(<img src="#{url}" alt="#{name}">) elsif blob.content_type.to_s.start_with?("video/") %(<video controls src="#{url}"></video>) else %(<a href="#{url}" download="#{name}" data-filesize="#{blob.byte_size}">#{name}</a>) end end |
#attachments_embeddable? ⇒ Boolean
GitHub-synced creatives reject any description change (description_cannot_change_if_github_source), so embedding would raise and orphan the blob. Callers MUST check this before creating the blob.
45 46 47 |
# File 'app/models/collavre/creative/describable.rb', line 45 def !effective_origin.github_markdown? end |
#creative_snippet ⇒ Object
38 39 40 |
# File 'app/models/collavre/creative/describable.rb', line 38 def creative_snippet CGI.unescapeHTML(ActionController::Base.helpers.(effective_origin.description || "")).truncate(24, omission: "...") end |
#effective_description(variation_id = nil, html = true) ⇒ Object
Linked Creative의 description을 안전하게 반환
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'app/models/collavre/creative/describable.rb', line 25 def effective_description(variation_id = nil, html = true) if variation_id.present? variation_tag = .find_by(label_id: variation_id) return variation_tag.value if variation_tag&.value.present? end description_val = origin_id.nil? ? description : origin.description if html description_val&.to_s || "" else ActionController::Base.helpers.(description_val&.to_s || "") end end |
#embed_attachment_blob!(blob) ⇒ Object
Append an attachment node and save; after_save reconcile attaches the blob to creative.files. Linked creatives can’t change their own description (it lives on the origin), so embed on effective_origin —otherwise the save raises and orphans the blob.
53 54 55 56 57 58 59 60 61 62 63 |
# File 'app/models/collavre/creative/describable.rb', line 53 def (blob) target = effective_origin return target.(blob) unless target == self node = (blob) new_html = "#{description}#{node}" # Markdown-mode creatives derive description from markdown_source; demote # to HTML so the embedded node is the persisted source of truth. self.content_type_input = "html" if data&.dig("content_type") == "markdown" update!(description: new_html) end |
#remove_attachment!(signed_id) ⇒ Object
Remove the attachment for ‘signed_id`. HTML is the source of truth, so strip the node and let after_save reconcile detach + safe-purge. A blob that’s attached but not embedded (legacy, not yet backfilled) is detached directly. Returns true if an attachment was present.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'app/models/collavre/creative/describable.rb', line 84 def (signed_id) target = effective_origin return target.(signed_id) unless target == self blob = ActiveStorage::Blob.find_signed(signed_id) return false unless blob = files..find_by(blob_id: blob.id) return false unless stripped = (blob.signed_id) if stripped # Demote markdown -> html so the stripped HTML is the persisted source # of truth (mirrors embed_attachment_blob!). self.content_type_input = "html" if data&.dig("content_type") == "markdown" update!(description: stripped) else detach_and_maybe_purge() end true end |