2

In our rails 3.2 app, we are using Jbuilder to render our json responses (nothing special here). The json view could be as simple as this:

_model_name.json.jbuilder

json.extract!(page, :id, :name, :url_name)

We often need to return a deeply nested json object, and Jbuilder partials work great for this:

_page.json.jbuilder

json.extract!(page, :id, :name, :url_name)
json.page_images (page_images) do |json, page_image|
    json.partial! page_image
end

The last example will retrieve the page, and nested page_images, json representation... again nothing special.

Often, a single partial will call another, and may return a nested json object 2 or 3 levels deep.

PROBLEM

Like I mentioned above, we use Jbuilder partials to quickly link multiple partials together to form a deeply nested json object for the view. We also need build these exact same nested objects as a hash (rather than json) AND make them available to a model.

It's simple to get a Jbuilder object to output a hash using the .attributes! method, but we're having some serious difficultes giving Jbuilder access to the view partials from a model.

Looking at the Jbuilder source, it looks like the JbuilderTemplate class needs access to the controller context to make everything work.

We might try something like this:

class SomeClass

  def initialize pages
    @pages = pages
    @context = ActionController::Base.new
  end

  def to_hash
     builder = JbuilderTemplate.new(@context)
     builder.pages(@pages) do |json, page|
        json.partial! page
     end
     builder.attributes!
  end
end

The example above is obviously incorrect, but it illustrates what needs to be done. I'm just not sure how to pass initialize a controller from a model, and then pass the controller context.

Some leads that we are following:

Can anyone help point us in the right direction?

4 Answers 4

2

I'm pretty sure you were on the right track here. You should be able to call json.array! and build the partial normally if you pass the block directly in the initializer.

def to_hash
  builder = JbuilderTemplate.new(@context) do |json|
    json.array! @pages, partial: 'path/to/partial'
  end
  builder.attributes!
end
Sign up to request clarification or add additional context in comments.

Comments

1

Couldn't find a solution. We fell back to using as_json to configure our model json output.

1 Comment

Have a look at my answer below if you still want to be able to reuse your jbuilder templates.
0

I use ActiveModel::Serializer to do this exact same thing. You can render the json in the model or whereever - we do this to pre-populate the cache.

The syntax for doing this wasn't initially obvious, so I'm posting here:

ItemSerializer.new(item).to_json

Comments

0

If you really need this functionality, I can show you some shim:

c = ActionController::Base.new
c.instance_variable_set '@item', Item.find(5)
JSON.parse c.render_to_string('items/show')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.