Hock
Hock

Reputation: 5804

Remove all html tags from attributes in rails

I have a Project model and it has some text attributes, one is summary. I have some projects that have html tags in the summary and I want to convert that to plain text. I have this method that has a regex that will remove all html tags.

def strip_html_comments_on_data
  self.attributes.each{|key,value| value.to_s.gsub!(/(<[^>]+>|&nbsp;|\r|\n)/,"")}
end

I also have a before_save filter

before_save :strip_html_comments_on_data

The problem is that the html tags are still there after saving the project. What am I missing?

And, is there a really easy way to have that method called in all the models?

Thanks,

Nicolás Hock Isaza

Upvotes: 15

Views: 22132

Answers (6)

Abhinaya
Abhinaya

Reputation: 809

If you want to remove &nbsp; along with html tags, nokogiri can be used

include ActionView::Helpers::SanitizeHelper

def foo
  sanitized_output = strip_tags(html_input)
  Nokogiri::HTML.fragment(sanitized_output)
end

Upvotes: 0

scarver2
scarver2

Reputation: 7995

Reference Rails' sanitizer directly without using includes.

def text
  ActionView::Base.full_sanitizer.sanitize(html).html_safe
end

NOTE: I appended .html_safe to make HTML entities like &nbsp; render correctly. Don't use this if there is a potential for malicious JavaScript injection.

Upvotes: 1

wanderfalke
wanderfalke

Reputation: 878

It would be better not to include view helpers in your model. Just use:

HTML::FullSanitizer.new.sanitize(text)

Upvotes: 11

simianarmy
simianarmy

Reputation: 1507

Just use the strip_tags() text helper as mentioned by zetetic

Upvotes: 3

zetetic
zetetic

Reputation: 47578

untested

include ActionView::Helpers::SanitizeHelper

def foo
  sanitized_output = sanitize(html_input)
end

where html_input is a string containing HTML tags.

EDIT

You can strip all tags by passing :tags=>[] as an option:

plain_text = sanitize(html_input, :tags=>[])

Although reading the docs I see there is a better method:

plain_text = strip_tags(html_input)

Then make it into a before filter per smotchkiss and you're good to go.

Upvotes: 47

maček
maček

Reputation: 77826

First, the issue here is that Array#each returns the input array regardless of the block contents. A couple people just went over Array#each with me in a question I asked: "Return hash with modified values in Ruby".

Second, Aside from Array#each not really doing what you want it to here, I don't think you should be doing this anyway. Why would you need to run this method over ALL the model's attributes?

Finally, why not keep the HTML input from the users and just use the standard h() helper when outputting it?

# this will output as plain text
<%=h string_with_html %>

This is useful because you can view the database and see the unmodified data exactly as it was entered by the user (if needed). If you really must convert to plain text before saving the value, @zetetic's solution gets you started.

include ActionView::Helpers::SanitizeHelper

class Comment < ActiveRecord::Base

  before_save :sanitize_html

  protected
  def sanitize_html
    self.text = sanitize(text)
  end

end

Upvotes: 1

Related Questions