YvesR
YvesR

Reputation: 6232

Rails Active Record .to_yaml different output for text content

We do use .to_yaml on ActiveRecord to dump some values of a record in to a .yml file for backup reasons.

Those files are stored into a repository as those backup data is part of defaults for setup new systems.

Example:

---
guid: dbYSoCvkzq9z5ZFyRxy0lE
name: bookmarklisting
template: |-
  <div class="template">
    <tpl for=".">
      <div class="x-like-menu-item pointer selection {[xindex%2==0 ? "even" : "odd"]}">
        {[Ext.String.htmlEncode(values.topic||values.title||t("infobase.missing_topic"))]}
      </div>
    </tpl>
  </div>
config: "{ foo:true }"
deactivated: false
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: 2012-03-01 13:31:47.296000000 Z
  zone: &1 !ruby/object:ActiveSupport::TimeZone
    name: Europe/Berlin
  time: 2012-03-01 14:31:47.296000000 Z
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: 2021-05-20 16:32:01.093000000 Z
  zone: *1
  time: 2021-05-20 18:32:01.093000000 Z
actors: "-4"
group_name: ''

As you can see the template contains long html template data. So far so good. This works fine and perfect, and if something changes its easy to diff in pull requests.

But for some reason sometimes the text content gets escaped.

Example:

---
guid: aPsOeyYUbumlfZI2yLs2ti
name: infobase
template: "<tpl for=\".\">\n  <a name=\"infobase-{id}\"></a>\n\n  <div class=\"papersheet\"
  style=\"padding:0\">\n    <tpl if=\"folder.folder_type\">\n      <tpl if=\"folder.folder_type.tools.length
  &gt; 0\"><div class=\"buttoncontainer border-bottom\"></div></tpl>\n    </tpl>\n
  \   \n    {[this.infobase.messages(values)]}\n\n    <div class=\"infobase\" style=\"padding:
  5mm 15mm\">\n\n      <div class=\"header greytext border-bottom\">\n        <div
  data-qtip=\"{folder.path}/{folder.name}\">{folder.name:htmlEncode}</div>\n        <div>\n
  \         <tpl if=\"owner.mail\"><a href=\"mailto:{owner.mail}?subject={[escape(values.topic)]}\">{owner.name:htmlEncode}</a></tpl>\n
  \         <tpl if=\"!owner.mail\">{owner.name}</tpl>\n        </div>\n        <div>{[Ext.util.Format.date(values.changed_at,
  InformerContext.format.dateshort)]}</div>\n      </div>\n\n      <div class=\"largetext
  boldtext\" style=\"line-height: 22px;margin:10px 0;\">{topic}</div>\n\n      <tpl
  if=\"attachment.file||attachment.source\">\n        <div class=\"linkcontainer border-bottom\">\n
  \         <tpl if=\"attachment.file\">{attachment.file:this.attachment.link}<br
  /></tpl>\n          <tpl if=\"attachment.source\">{attachment.source:this.attachment.link}</tpl>\n
  \       </div>\n      </tpl>\n\n      <div class=\"content\"><div>{description:nl2br}</div></div>\n\n
  \     <tpl if=\"locked\"><div class=\"lockedcontent mediumtext\">{[t(\"infobase.messages.record_locked\")]}</div></tpl>\n
  \     <tpl if=\"content.length &gt; 0 && locked == false\">\n        <div class=\"content
  clear\">{content}</div>\n        <tpl if=\"attachment.file.media.type == 'video'\"><center>{attachment.file:this.attachment.html5video}</center></tpl>\n
  \       <tpl if=\"attachment.file.media.type == 'flv'\"><center>{attachment.file:this.attachment.flashvideo}</center></tpl>\n
  \     </tpl>\n\n      <tpl if=\"members.length &gt; 0 || member_of.length &gt; 0\">\n
  \       <div class=\"membercontainer border-top\">\n          <tpl if=\"members.length
  &gt; 0 \">\n            <div class=\"memberscontainer\">\n              <span class=\"boldtext\">{[t(\"infobase.effective_documents\")]}</span>\n
  \             <ul>\n              <tpl for=\"members\">\n                <li>\n
  \                 <a href=\"{url.reader}\" target=\"_reader\" data-qtip=\"{[t(\"infobase.folder\")]}:
  {folder.name}\">{topic:htmlEncode}</a>\n                  <tpl if=\"attachment.file\">{attachment.file:this.attachment.iconlink}</tpl>\n
  \               </li>\n              </tpl>\n              </ul>\n            </div>\n
  \         </tpl>\n          <tpl if=\"member_of.length &gt; 0 \">\n            <div
  class=\"memberofcontainer\">\n              <span class=\"boldtext\">{[t(\"infobase.effective_document_of\")]}</span>\n
  \             <ul>\n              <tpl for=\"member_of\">\n                <li>\n
  \                 <a href=\"{url.reader}\" target=\"_reader\" data-qtip=\"{[t(\"infobase.folder\")]}:
  {folder.name}\">{topic:htmlEncode}</a>\n                  <tpl if=\"attachment.file\">{attachment.file:this.attachment.iconlink}</tpl>\n
  \               </li>\n              </tpl>\n              </ul>\n            </div>\n
  \         </tpl>\n          <br style=\"clear:both\"/>\n        </div>\n      </tpl>\n\n
  \     <!--// Alle Zusatzfelder ausgeben //-->\n      <table class=\"profile-table\"
  cellpadding=0 cellspacing=0>\n      <tpl for=\"profiles.keys\">\n        <tr>\n
  \         <th>\n            {[ this.infobase.label(parent[0].profiles[values]) ]}:\n
  \         </th>\n          <td>\n            {[ this.infobase.value(parent[0].profiles[values])
  ]}\n          </td>\n        </tr>\n      </tpl>\n      </table>\n\n    </div>\n
  \ </div>\n</tpl>"
config: "{}"
deactivated: false
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: 2011-10-11 10:26:08.906000000 Z
  zone: &1 !ruby/object:ActiveSupport::TimeZone
    name: Europe/Berlin
  time: 2011-10-11 12:26:08.906000000 Z
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: 2021-04-30 09:12:12.726000000 Z
  zone: *1
  time: 2021-04-30 11:12:12.726000000 Z
actors: "-4"
group_name: infobase

It has so far I can see nothing todo with then length or any special chars, in fact I did not find out what the reason is. I do want to always store template data in like the first example.

So how and when .to_yaml decide to escape the data or not and how can I do prevent this behavior?

Upvotes: 0

Views: 144

Answers (1)

cschroed
cschroed

Reputation: 6899

The issue is with lines that include only spaces.

These will format how you want:

puts({ text: "Text A\nText B" }.to_yaml)
---
:text: |-
  Text A
  Text B

puts({ text: "Text A\n\nText B" }.to_yaml)
---
:text: |-
  Text A

  Text B

But this won't:

puts({ text: "Text A\n \nText B" }.to_yaml)
---
:text: "Text A\n \nText B"

This behavior may be so that it doesn't end up producing YAML that isn't formatted correctly. You may want to strip blank lines out before saving the data or before serializing.

Upvotes: 1

Related Questions