Search code examples
ruby-on-railsview-helpers

Rails: Render view content in post-processor (model / helper issues)


I have a web app in which I also have quite a complex type of blog. For this blog I use both RedCarpet as markup language in addition to a homemade markup language, that is very useful.

In my homemade markup language I call Product-views and other partials from the app. I use this in two different models: BlogPost and Article.

For example, a blog post could be something like:

@blog_post.unprocessed_content = "Today I would like to show you this **cool** product that we offer: [[PRODUCT#ID:123]]." 

The [[PRODUCT#ID:123]] is my own markup language and cool is RedCarpet. I use a render_content method from ApplicationHelper like this:

processed_content = render_content(@blog_post.unprocessed_content)

which would output

processed_content = "Today I would like to show you a <strong>cool</strong> product that we offer: <h3>Apple</h3><img src="apple.jpg"><p>Apple is a nice fruit.</p>. Price: 1 USD."

The "apple" part is fetched from a a view-partial.

The method in ApplicationHelper uses for example: - render partials /blog_post/product_item_with_pic - RedCarpet markup

I write all articles/blog posts in an markup/unprocessed state but it would make total sense to pre-process this content when I publish and have render_content() loaded on :before_save.

The problem

Basically, I would like to use that :before_save from the BlogPost and Article model but then I run into the issue of trying to do helper stuff from within a model and it all gets messy.

I tried to use:

ApplicationController.helpers.render_content(@blog_post.unprocessed_content)

but then it can't find the view-partials like /blog_post/product_item_with_pic . It feels like I would just keep on bumping into issues like this.

Right now, I have a VERY ugly solution (that works) and it is to have the preprocessing being done in the view when the view is loaded. Basically, in admin::blog_post#show I call render_content and then perform a save. Yeah, it's ugly.

My questions

  1. What would be the most elegant way of solving this?
  2. If there isn't really a good way, at least, how can I access partials when I call the ApplicationHelper like this from the model?

Solution

  • I'm not sure I understand completely what you want. But to use Rails view rendering capabilities outside of standard flow one should use render_anywhere gem.

    require 'render_anywhere'
    
    class Article < ActiveRecord::Base
      include RenderAnywhere
      class RenderingController < RenderAnywhere::RenderingController; end
    
      before_save :process_content
      attr_reader :content
    
      private
    
      def process_content
        # This variable will contain resulting HTML
        @content = render(template: 'articles/article', layout: 'articles')
      end
    end
    

    Read the brief documentation for information on how to make helper available inside of your renderer.