nesquena / rabl

General ruby templating with json, bson, xml, plist and msgpack support
http://blog.codepath.com/2011/06/27/building-a-platform-api-on-rails/
MIT License
3.65k stars 335 forks source link

how to pass instance variables between templates? #363

Open josh-m-sharpe opened 11 years ago

josh-m-sharpe commented 11 years ago

I've got users/show:

object @user

attribute :id
node :foo do
  @test
end

child :accounts do
  extends 'accounts/show', :locals => {:test => @test}
end

node :accounts2 do |obj|
  partial 'accounts/show', :object => obj.accounts, :locals => {:test => @test}
end

and accounts/show

object @account

attribute :id
node :foo do
  @test
end

If I do this:

Rabl::Renderer.json(user, 'users/show', :locals => {:test => 123})

the :foo attribute is nil in the accounts. Is there any way to pass an instance variable through to another partial?

{"accounts"=>[{"id"=>252618, "foo"=>nil}, {"id"=>2521838, "foo"=>nil}],
 "accounts2"=>[{"id"=>252618, "foo"=>nil}, {"id"=>2521838, "foo"=>nil}],
 "id"=>144,
 "foo"=>123}
databyte commented 11 years ago

Child can be given a block variable but it'll be @user and not any arbitrary variable. I'm not sure I've even done that since I'm fairly allergic to multiple instance variables in the view. Maybe @nesquena knows.

josh-m-sharpe commented 11 years ago

At a minimum, I need a hack of a solution so I can keep moving. From within a template is there any object I can hook into that'll also be available in the next template?

I'm thinking of just setting my own instance variable on something.

josh-m-sharpe commented 11 years ago

Bah, didn't mean to do that.

agibralter commented 11 years ago

Well I think you could probably figure out a way to wrap the instance variable into the object in a more OO style... but if you have to hack it, you could probably pass something into the scope, as a helper method would be:

Rabl::Engine.new("...source...", { :format => "xml" }).render(scope, { :foo => "bar", :object => @user })
databyte commented 11 years ago

Yeah, I was thinking there is a shortcut but my typical response is to use a presenter. Here's my boilerplate response on why there should only be one object at the top of your RABL and why everything should derive from there:

Great articles to read:

I cover most of the above with Testing in isolation, example in RABL on my blog. After writing that, I recently read Objects on Rails and found that Avdi Grimm covers much of the same but explains it better in book format.

nesquena commented 11 years ago

Completely agree whenever I see multiple instance variables or really complex logic in nodes in rabl, I usually extract it into a PORO. A simple ruby object that acts as a presenter which can be tested easily and in isolation.

On Nov 21, 2012, at 9:37 AM, David Sommers notifications@github.com wrote:

Yeah, I was thinking there is a shortcut but my typical response is to use a presenter. Here's my boilerplate response on why there should only be one object at the top of your RABL and why everything should derive from there:

Presentation and another Delegation Decorator example Cache all output and more Great articles to read:

Decorators compared to Strategies, Composites, and Presenters Better Ruby Presenters I cover most of the above with Testing in isolation, example in RABL on my blog. After writing that, I recently read Objects on Rails and found that Avdi Grimm covers much of the same but explains it better in book format.

— Reply to this email directly or view it on GitHub.