5

I'm creating a Rails 6.0.0 App and it has the following modules:

  • Web - Forms / Cruds
  • Api

There's a CRUD where I use Action Text. The form is working OK, I successfully implemented the Action Text artifacts.

Moving forward, I've created a JSON API that exposes the resources created through the forms. The output JSON looks like this:

{
    "id": 3,
    "title": "Happy title",
    "content": {
        "id": 1,
        "name": "content",
        "body": "<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eget tortor venenatis elit laoreet sagittis. In hac habitasse platea dictumst. Mauris nec nisl dapibus sem volutpat ultricies vel eu erat. Nunc at aliquet diam, vel pretium velit. <br><br><action-text-attachment sgid=\"BAh7CEkiCGdpZAY6BkVUSSI0Z2lkOi8vZXhpbi13ZWIvQWN0aXZlU3RvcmFnZTo6QmxvYi81P2V4cGlyZXNfaW4GOwBUSSIMcHVycG9zZQY7AFRJIg9hdHRhY2hhYmxlBjsAVEkiD2V4cGlyZXNfYXQGOwBUMA==--8f909146395a3dede0d4d5e47ad54d82d9e06367\" content-type=\"image/png\" url=\"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6a79e95fd7a0fc0883190bd1201d4f5ecb1f8445/qrcode%20(2).png\" filename=\"qrcode (2).png\" filesize=\"497\" width=\"400\" height=\"400\" presentation=\"gallery\"></action-text-attachment><br><br><strong>Phasellus</strong> at dictum ligula. Sed tempus odio sed elit ultricies, in pulvinar purus dictum. Suspendisse sit amet fermentum lacus. Suspendisse sed tristique lectus.</div>",
        "record_type": "Announcement",
        "record_id": 3,
        "created_at": "2019-10-30T23:25:24.080Z",
        "updated_at": "2019-10-30T23:25:24.138Z"
    },
    "created_at": "2019-10-30T23:25:24.039Z",
    "updated_at": "2019-10-30T23:25:24.139Z"
}

PROBLEM:

If you see, the content.body attribute has Rails Action Text tags:

<action-text-attachment sgid...>

In the form at the end of the day the Rails Action Text converts this tag into a figure HTML tag like this in order to render the Images:

<figure class="attachment attachment--preview attachment--png">
    <img src="http://localhost:3000/rails/active_storage/representations/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBDZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6a79e95fd7a0fc0883190bd1201d4f5ecb1f8445/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCam9VY21WemFYcGxYM1J2WDJ4cGJXbDBXd2RwQWdBRWFRSUFBdz09IiwiZXhwIjpudWxsLCJwdXIiOiJ2YXJpYXRpb24ifX0=--defcd74f258f74bba5b028de265f7a5858cffd0b/qrcode%20(2).png">

  <figcaption class="attachment__caption">
      <span class="attachment__name">qrcode (2).png</span>
      <!--<span class="attachment__size"></span>-->
  </figcaption>
</figure>

QUESTION:

How can I render the same HTML with the JSON API?

I need to expose this content in order to render it in several client apps.

Luis de Haro
  • 711
  • 1
  • 7
  • 28

2 Answers2

4

So I made a dummy column to populate on the model's before_save callback with the raw output from Action Text.

has_rich_text :rich_body

before_save :update_old_body

private

def update_old_body
  self.body = rich_body&.body&.to_s unless body
end

Then I put body in my serializer to generate the JSON.

However, if you want to migrate older records you'll have to create the Action Text record manually, otherwise you'll get very persistent undefined method 'render_action_text_content' errors. In my case changing the callback to this did it:

def update_old_body
  self.body = rich_body&.body&.to_s unless body
rescue ActionView::Template::Error
  build_rich_text_rich_body
end

Done.

Update

If you have attachments you're going to want to change it to:

self.body = rich_body&.body&.to_rendered_html_with_layout

Save yourself a world of hurt.

t56k
  • 6,769
  • 9
  • 52
  • 115
2

Let's say I have has_rich_text :description. In order to get pure body I would need to call it with description.body.to_s as it gives me:

"<div class=\"trix-content\">\n  <div>test</div>\n</div>\n"

However simple description.body would give me:

#<ActionText::Content "<div class=\"trix-conte...">
matiss
  • 747
  • 15
  • 36
  • This doesn't work because calling Action Text looks for other methods on `.body` like `.render_action_text_content`. I've solved it in a really hacky way in my answer. – t56k Mar 19 '20 at 03:34
  • @okay56k that's great! Where is your answer: even if hacky, people (ahem: myself) would love to see it. If you can post it, please do – BenKoshy Mar 19 '20 at 03:37
  • 1
    @BKSpurgeon Solved and posted :) – t56k Mar 19 '20 at 06:50
  • That's correct, rich_text_field.body.to_s gives you the pure html content. – Luis de Haro Mar 19 '20 at 16:28