Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rabl.render: how to use view helper methods?

I'm using Rabl to generate XML output in a rake task:

xml = Rabl.render @listings, 'feeds/listings', :format => :xml
# do stuff with xml

However, I need to use multiple helper methods in the rabl view file referenced, and I keep getting a NoMethodError as I expected from the answer to this question.

I tried using extends and include in the class used by the rake task but I still get the same error on the helper methods:

require "#{Rails.root}/app/helpers/feeds_helper.rb"

class SerializeData
  extends FeedsHelper

  def perform
    xml = Rabl.render @listings, 'feeds/listings', :format => :xml
    # do stuff with xml
  end
end

My question is: is there any way to use helper methods in rabl view files generated in this way? (or at least in a way that I can still render them as a string in a rake task?) The helper methods are used many, many times to correctly format various data per fixed requirements, so it would be very difficult to remove them entirely.

like image 502
eirikir Avatar asked Aug 06 '13 22:08

eirikir


2 Answers

I ended up with a monkey-patchy solution.

I noticed that the NoMethodFound error came from an instance of the Rabl::Engine class, so I included the needed routing and helper methods in that class and was then able to access them:

require "#{Rails.root}/app/helpers/feeds_helper.rb"
...
class Rabl::Engine
  include Rails.application.routes.url_helpers
  include FeedsHelper
end

Also note that the URL host needs to be set if using url in addition to path helpers (e.g. root_url and root_path):

Rails.application.routes.default_url_options[:host] = "www.example.com"

I would definitely prefer a non-monkey-patch solution or at least one where helpers could be included as needed depending on the controller of the action rendered. I'll wait to accept this to see if anyone can come up with such an answer.

like image 159
eirikir Avatar answered Sep 23 '22 23:09

eirikir


You can pass in a scope object with the scope parameter. So if you have access to an object with the helper included, like when in the view context, then you can pass that eg:

<%= Rabl::Renderer.json(object_to_render, 'api/v1/object/show', view_path: 'app/views', scope: self).html_safe%>

So outside of the view context you'd need to pass in a custom object with the helpers included to make this clean. eg

class RakeScope
  include FeedHelper
end

Rabl::Renderer.json(object_to_render, 'api/v1/object/show', view_path: 'app/views', scope: RakeScope.new() )

I've not tried the second option but the first works great.

like image 39
toxaq Avatar answered Sep 23 '22 23:09

toxaq