Forcing a specific :format using Rabl::Renderer.json w/ :scope option set. #315

Open
veloper opened this Issue Aug 21, 2012 · 9 comments

Comments

Projects
None yet
5 participants
@veloper

veloper commented Aug 21, 2012

I was wondering if there was a way to force the underlying renderer to use a specific format when using Rabl::Renderer when the :scope option is specified.

My views are currently named like so xxxxx.json.rabl and as such need to have a specific :format of json

My views also make use of a helper method defined in the application controller called include? which reads params[:_include] and figures out if a relationship should be included as child node.

Scenario

URL

/api/v1/clients.csv?_include=2

Controller

class ApplicationController < ActionController::Base

  helper_method :include?
  before_filter :catch_csv

  def catch_csv
    return unless params[:format] == 'csv'
    json = Rabl::Renderer.json(@collection, "#{params[:controller]}/index", :view_path => 'app/views', :scope => self)
    ... parse and turn into CSV 
  end

  def include?
    # logic to determine include depth
  end

end

Problem

With this example I get the following exception...

ActionView::MissingTemplate (Missing partial api/v1/clients/show with {:locale=>[:en], :formats=>[nil], :handlers=>[:erb, :builder, :rabl]}

You'll notice this part :formats=>[nil] -- as "csv" is not a valid format type in (https://github.com/nesquena/rabl/blob/master/lib/rabl/engine.rb#L6)

Looking at the Engine class it appears to set the format here: https://github.com/nesquena/rabl/blob/master/lib/rabl/engine.rb#L28 ...which calls this method here: https://github.com/nesquena/rabl/blob/master/lib/rabl/engine.rb#L211 seemingly checking the scope i passed in.

The problem is that I need the include? helper method to be available to the RABL views, but I don't want the controllers :format to be used in a manual rendering call.

The only solution I've found seems very ugly and wrong to me... but it works...

Ugly Solution

class RablControllerWrapper
  attr_reader :controller
  def initialize(controller)
    @controller = controller
  end

  def include?
    @controller.include?
  end
end

json = Rabl::Renderer.json(@collection, "#{params[:controller]}/index", 
  :view_path => 'app/views', 
  :scope => RablControllerWrapper.new(self)
)   

Pointers, thoughts, opinions?

Thanks :)

@nesquena

This comment has been minimized.

Show comment
Hide comment
@nesquena

nesquena Aug 21, 2012

Owner

I see, it looks like we might need to tweak rabl to adhere to an explicitly specified format more closely? Since you specified:

Rabl::Renderer.json(@collection, "#{params[:controller]}/index", :view_path => 'app/views', :scope => self)

it follows that it should try and render the format as JSON rather than CSV. I will have to dig in more later to see if this can be fixed easily. Thanks for raising the issue.

Owner

nesquena commented Aug 21, 2012

I see, it looks like we might need to tweak rabl to adhere to an explicitly specified format more closely? Since you specified:

Rabl::Renderer.json(@collection, "#{params[:controller]}/index", :view_path => 'app/views', :scope => self)

it follows that it should try and render the format as JSON rather than CSV. I will have to dig in more later to see if this can be fixed easily. Thanks for raising the issue.

@veloper

This comment has been minimized.

Show comment
Hide comment
@veloper

veloper Aug 21, 2012

Thanks for the quick reply. For now I'll continue on with a wrapper class.

veloper commented Aug 21, 2012

Thanks for the quick reply. For now I'll continue on with a wrapper class.

@nesquena

This comment has been minimized.

Show comment
Hide comment
@nesquena

nesquena Aug 21, 2012

Owner

Yeah that was a clever (albeit unfortunate) workaround. Hopefully we can fix this soon.

Owner

nesquena commented Aug 21, 2012

Yeah that was a clever (albeit unfortunate) workaround. Hopefully we can fix this soon.

@veloper

This comment has been minimized.

Show comment
Hide comment
@veloper

veloper Aug 21, 2012

Out of curiosity, and if you know off the top of your head, what method/attributes is my wrapper class blocking the library from accessing where it determines the format?

veloper commented Aug 21, 2012

Out of curiosity, and if you know off the top of your head, what method/attributes is my wrapper class blocking the library from accessing where it determines the format?

@databyte

This comment has been minimized.

Show comment
Hide comment
@databyte

databyte Sep 5, 2012

Collaborator

If you want to make a failing test for it, I can tweak it to work because by the looks of it, I would've guessed you can pass in the format and it won't use the request_format method.

Rabl.render(object, template, :view_path => 'app/views', :format => :csv)
Collaborator

databyte commented Sep 5, 2012

If you want to make a failing test for it, I can tweak it to work because by the looks of it, I would've guessed you can pass in the format and it won't use the request_format method.

Rabl.render(object, template, :view_path => 'app/views', :format => :csv)
@mateusmaso

This comment has been minimized.

Show comment
Hide comment
@mateusmaso

mateusmaso Oct 1, 2012

Getting the same problem here :/

Getting the same problem here :/

@databyte

This comment has been minimized.

Show comment
Hide comment
@databyte

databyte Nov 20, 2012

Collaborator

Anyone want to make a failing test or sample app for me to fix?

Collaborator

databyte commented Nov 20, 2012

Anyone want to make a failing test or sample app for me to fix?

@ghost ghost assigned databyte Nov 20, 2012

@sockmonk

This comment has been minimized.

Show comment
Hide comment
@sockmonk

sockmonk Jan 7, 2013

I'm seeing a very similar issue. It looks like Rabl::Engine#request_format is relying on request_params / context_scope.params to choose the format, rather than @_options[:format] that stores the format the user passed in. Then in Rabl::Partials#fetch_rails_source it uses that for the source_format, with the result that rabl partials aren't found when I try to use them via gon.

I think that Rabl::Engine#request_format should take @_options[:format] into consideration if it's been set. Hope this gets someone closer to fixing this.

sockmonk commented Jan 7, 2013

I'm seeing a very similar issue. It looks like Rabl::Engine#request_format is relying on request_params / context_scope.params to choose the format, rather than @_options[:format] that stores the format the user passed in. Then in Rabl::Partials#fetch_rails_source it uses that for the source_format, with the result that rabl partials aren't found when I try to use them via gon.

I think that Rabl::Engine#request_format should take @_options[:format] into consideration if it's been set. Hope this gets someone closer to fixing this.

@nesquena

This comment has been minimized.

Show comment
Hide comment
@nesquena

nesquena Jan 8, 2013

Owner

Thanks for tracking that down, hopefully one of us can take a look soon. In the mean time, any pull requests greatly appreciated :)

Owner

nesquena commented Jan 8, 2013

Thanks for tracking that down, hopefully one of us can take a look soon. In the mean time, any pull requests greatly appreciated :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment