6

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.

4

3 回答 3

7

我最终得到了一个猴子补丁的解决方案。

我注意到NoMethodFound错误来自该类的一个实例Rabl::Engine,因此我在该类中包含了所需的路由和辅助方法,然后能够访问它们:

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

url另请注意,如果使用除了path帮助程序(例如root_url和)之外,还需要设置 URL 主机root_path

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

我肯定更喜欢非猴子补丁解决方案,或者至少一个可以根据需要包含帮助程序的解决方案,具体取决于所呈现操作的控制器。我会等待接受这个,看看是否有人能提出这样的答案。

于 2013-08-08T19:08:38.967 回答
4

您可以使用范围参数传入范围对象。因此,如果您可以访问包含帮助程序的对象,例如在视图上下文中,那么您可以传递它,例如:

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

因此,在视图上下文之外,您需要传入一个包含帮助程序的自定义对象以使其干净。例如

class RakeScope
  include FeedHelper
end

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

我没有尝试过第二种选择,但第一种效果很好。

于 2013-11-10T21:41:37.437 回答
0

虽然不是完全相同的问题,但我在访问 RSpec 规范中的助手时遇到了类似的问题。我创建了一个辅助函数,它创建了一个范围,您可以使用它来添加您需要的任何辅助函数。以下内容让我可以访问路径和 url 辅助方法,类似的东西应该适用于 Rake。

#spec/support/rabl_helper.rb
def render_rabl(object, options={})
  options = {
    format:    'json',
    view_path: 'app/views',
    file:      example.example_group.top_level_description,
    scope:     RablScope.new
  }.merge(options)

  result = Rabl.render(object, options.delete(:file), options)
  options[:format] == 'json' ? JSON.parse(result) : result
end

class RablScope
  include Rails.application.routes.url_helpers
end
于 2014-01-16T22:31:07.040 回答