#rails #rich_text #trix #concerns 🇬🇧

Add a target blank to link in rich text with ruby on rails

Jeanro Krupa

Jeanro Krupa

2 min read
When a user click on a link present in a rich_text it does not open in a new page... It is something very annoying for some of our users at Komin.io. We build a LMS and we are leveraging a lot of the RichText / Trix editor features. Unfortunately it is not a default in Rails and not present in the documentation either. The solution implemented has been inspired by this issue: https://github.com/basecamp/trix/issues/55

At Komin.io we have a lot of models that has_rich_text :something. Some requirements
  • The name of the attribute is not always the same (:body, :text, :comment_body....) 
  • Sometimes we have many different rich_text elements for a single class...
  • For one specific model we don't the target blank

We created a concern:
# app/models/concerns/rich_text_target_blank.rb
module RichTextTargetBlank
  extend ActiveSupport::Concern

  class_methods do
    # Override has_rich_text to include target="_blank" functionality
    def has_rich_text(name)
      super(name) # Call the original has_rich_text to set up the rich text association

      # Define the before_save callback to modify the links
      before_save do
        rich_text_attribute = self.send(name)
        if rich_text_attribute.present?
          doc = Nokogiri::HTML::DocumentFragment.parse(rich_text_attribute.body.to_html)
          doc.css('a').each { |a| a['target'] = '_blank' }
          rich_text_attribute.body = doc.to_html
        end
      end
    end
  end
end
The concept is to override the has_rich_text method to add a `before_save` callback.

In the callback we parse with Nokogori all the `<a>`html tags and add the attribute target="_blank" on it.

Then we simple have to include the concern inside our class.

class Comment < ApplicationRecord
  include RichTextTargetBlank

  has_rich_text :body
end


The last thing to do if you want to modify the existing RichText attachments that you may have in production is to call .save on all the instances.

Comment.all.map(&:save)

We could also had a no follow attribute but not required in our case because our pages are not indexed by the browsers.



Feed
Sign up or Sign in to comment