Tree
Tree

Reputation: 1248

Render output of HTML stored in database in Rails

I have some html content stored in a database field. I would like trusted admins in our system to be able to edit the HTML when needed. Eventually this html will be converted into an email message and sent to users. In addition to the static html content, the email message has a first and last name that is stored in an active record model.

I was hoping to leave the <%= user.firstname user.lastname %> inside the HTML text when the admins are editing the content and then eventally combine the content with embedded erb the email renderer. I have the part where the admins can save the HTML working fine.

However, even ignoring the email and just trying to render to a normal web page, I am not able to get a view to correctly substitute the embedded <%= ... %> with the information from the database. I always see the <%= ... %> instead of the substituted text. I have tried render_to_string, render :inline, etc.

In summary, I am trying to:

  1. Take some html text with embedded some erb from the database
  2. Run the text through a template where the embedded erb is replaced with the variables passed into locals
  3. Take the resulting text block and either email it to users or display on a web page depending on my needs

The problem is that the results always have the <%= ... %> in it instead of the substitutions.

In an example controller I have:

 def showit
    @storedhtml = mymodel.savedhtml
    @emailtext = render_to_string( template: 'e.html.erb',
      layout: false, locals: { user:@user })
   end

The e.html.erb contains:

<%= raw @storedhtml %>

and the showit.html.erb has:

= raw @emailtext

I have also tried using inline like this:

def showit
     # the line below is substituted but the <p> tags are not converted
    @stuff = "<%= '<p>testme</p>' + user.firstname %>"  
    @storedhtml = mymodel.the_html_content
    @output = render( inline: @storedhtml, locals: { user:@user }, layout: true )
end

Upvotes: 1

Views: 5223

Answers (3)

jcgil
jcgil

Reputation: 1752

Assuming you have a Model with attribute named "template" which returns some html template (with ERB), if you want to render it you can use something like this into your controller's action:

render inline:"<%= raw ERB.new(@your_var.template).result(binding) %>".html_safe, layout:'application'

Upvotes: 0

sameera207
sameera207

Reputation: 16619

I guess what you need is 'liquid' - it's a template language for Rails.

Check this out:

http://liquidmarkup.org/

http://railscasts.com/episodes/118-liquid

Upvotes: 1

Dave Newton
Dave Newton

Reputation: 160170

In a controller you wouldn't use Erb syntax, you'd use normal Ruby string interpolation:

@stuff = "#{'<p>testme</p>'} #{user.firstname}"
# Or, since the HTML isn't dynamic:
@stuff = "<p>testme</p> #{user.firstname}"

And to output it in the view you'd need to use html_safe:

<%= @stuff.html_safe %>

In general, generating HTML directly in the controller isn't a great idea since there are other mechanisms in place, and it creates another place to look when you're trying to figure out what component creates which HTML.

Edit I misunderstood. Another templating engine like Sameera suggested is one option, or just evaluate the DB value as an erb template using your current binding.

You could also create a template resolution component that would allow retrieval directly from the DB if no file is found; the Crafting Rails Applications book discusses this.

Upvotes: 5

Related Questions