Cannot access routing URL helpers #231

Closed
BBonifield opened this Issue Apr 25, 2012 · 15 comments

Comments

Projects
None yet
7 participants

From what I gather from the docs, I should be able to use routing URL helpers in my RABL views, but that doesn't seem to be the case. Using rabl 0.6.10, rails 3.2.3.

show.json.rabl

object @reservation

attributes :id, :start_date, :end_date
node(:root) { root_url }

I get the following error

undefined local variable or method `root_url' for #<Rabl::Engine:0x00000103c54cf8>

vendor/bundle/gems/rabl-0.6.10/lib/rabl/engine.rb:228:in `method_missing'
vendor/bundle/gems/rabl-0.6.10/lib/rabl/builder.rb:76:in `call'
Owner

nesquena commented Apr 25, 2012

Can you try using rabl git master and see if it works? If it does, I will bump a patch release

No dice there. I have the same problem when I use gem 'rabl', :git => 'git://github.com/nesquena/rabl.git in my Gemfile.

However, I determined the root cause. I'm serializing my index data set to include as a data attribute on first load of the HTML page. As such, I'm doing Rabl::Renderer.json( @reservations, 'admin/reservations/index', :view_path => 'app/views'), and that is where the error is actually coming up. Do I need to do anything special to get my view helpers to work when I'm rendering templates in that fashiong?

Owner

nesquena commented Apr 25, 2012

Oh I see you are using the new renderer to do it. Yeah that changes the scope. You won't by default have access to your controller routes from within the render. You have to figure out the right scope:

Rabl::Renderer.json( @foo, 'bar', :scope => <object>)

Where <object> is a thing that responds to root_path. Where are you calling Renderer from?

I'm calling it from inside my index method. Essentially, I'm rendering the HTML index page with an JSON representation of the 'index' data as a data attribute on a DOM node. Based on what you said, I could pass in the controller as the scope?

I just wanted to confirm that passing the controller as the scope does indeed work. Thanks for the guidance!

Owner

nesquena commented Apr 25, 2012

Can you paste back the resulting renderer line with updated correct scope here for posterity? Thanks!

nesquena closed this Apr 25, 2012

Sure, the resulting setup was...

  def index
    @listing = Listing.find params[:listing_id]

    respond_to do |format|
      format.html {
        @index_json = Rabl::Renderer.json( @listing.reservations, 'admin/reservations/index', :view_path => 'app/views', :scope => self )
      } # index.html.erb
      format.json # index.json.rabl
    end
  end

I would just like to comment that using Rabl::Renderer is the only way to render a rabl partial from an html template on Rails 3.2.3. Using render does not work (and yes, I've looked at all the issues and commits surrounding getting it to work on Rails 3.2.3).

Owner

nesquena commented May 18, 2012

We have tests in place which actually verify that functionality: https://github.com/nesquena/rabl/blob/master/fixtures/ashared/views_rails_3/posts/index.html.erb and they seem to pass. Can you help me how your use differs from the fixture in rendering a rabl template from html. The test app is running Rails 3.2.3. Or perhaps suggest how we could add a failing test? /cc @databyte

Opened a new issue: #245

justinko referenced this issue May 18, 2012

Closed

Rails 3.2.3 #245

I am having trouble finding the correct scope to render a Rabl template with Rabl::Renderer.json that can access both the route and view helpers (e.g. simple_format). I have tried passing in the controller instance, the controller class, and the view_context with no luck. Any ideas?

Collaborator

databyte commented Jun 25, 2012

Can you create a new Issue and provide more details on the template and controller that renders the template. Also any error output for what you have already tried.

yesterday we have run into the same proble trying to render image_path in rabl template (rendered directly from model, so where was no view_context to pass in). Problem was with the scope object as mentioned before, so it taked some time to figure out correct object to pass in options.
the solution is:

def self.method_name(collection)
  Rabl::Renderer.json(collection, '/api/v2/specials/your_template', {:view_path => 'app/views', :scope => FakeContext.instance})
end

class FakeContext
    include Singleton
    include ActionView::Helpers::TagHelper
    # include ActionView::AssetPaths
    include Sprockets::Helpers::RailsHelper
    include Sprockets::Helpers::IsolatedHelper
    include ActionView::Helpers::AssetTagHelper
end

In this FakeContext you could include any helpers you need (this specific workaround allows you to use assets helpers specifically).
Hope it helps.

Owner

nesquena commented Aug 14, 2012

@romanonthego Good tip, thanks

mbferg commented Jun 9, 2013

I was dealing with the previous part of this issue, trying to render RABL directly into a Rails template using URL helpers, and came across this issue. @nesquena and @BBonifield's solution worked, I just thought I'd share my simple implementation as an example for anyone else confused:

class ApplicationController < ActionController::Base
  helper_method :render_json

  def render_json(object, template)
    Rabl::Renderer.json(object, template, scope: self)
  end
end

And then you just call render_json @users, 'users/index' as a helper method in the template. I'm using this to bootstrap data for Knockout.

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