Reputation: 5917
I'm using Rails as a REST server, and one of my models has a description field. In that model's JSON representation, I need to output both the regular description field AND an arbitrary non-DB attribute called description_markdown that is just the description run through a markdown filter. I already know how to run text through markdown using redcarpet, like:
@post = Post.find(params[:id])
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true, :fenced_code_blocks => true, :lax_html_blocks => true)
description_markdown = markdown.render(@post.description).html_safe
But what I really need is to make description_markdown
an attribute on @post (like @post.description_markdown), and have it output in @post's JSON representation.
Upvotes: 2
Views: 2407
Reputation: 4730
Just wanted to add an alternative in case you're defining what fields/data you need in the controller (like you might in a Rails 4 app), like so:
Post.to_json(only: [], methods: [:generate_markdown])
in your Post code, add:
def generate_markdown
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true, :fenced_code_blocks => true, :lax_html_blocks => true)
return markdown.render(@post.description).html_safe
Upvotes: 0
Reputation: 2859
I normally use RABL gem to build JSON views for my APIs -- it gives you a lot of flexibility on building JSON responses, such as creating custom child nodes, adding arbitrary code. Check it out.
But, to answer your question, you can probably overwrite as_json
method of Post
to include the return of description_markdown
. Something like (not tested):
#post.rb
class Post < ActiveRecord::Base
def description_markdown
...
end
...
def as_json(options)
super(:only => [:attributes_you_want], :methods => [:description_markdown])
end
...
end
Then, in controller:
render :json => @post
Hope, it helps.
Upvotes: 4
Reputation: 434685
You could add description_markdown
to your model:
def description_markdown
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true, :fenced_code_blocks => true, :lax_html_blocks => true)
markdown.render(description).html_safe
end
Then add that to your model's as_json
using :methods
:
def as_json(options = { })
super((options || { }).merge({
:methods => [:description_markdown]
}))
end
That would add your description_markdown
output to your model's standard JSON representation. The options || { }
is there in case someone hands you a nil
for options
, then we merge our :methods
into the options, and hand it off to ActiveRecord::Base for the heavy lifting. You'll need more complicated merging for options
if you want outsiders to be able to send in their own :methods
values.
Upvotes: 2