Haml::Engine.new("=link_to 'nowhere', ''").render no workie...

284 views
Skip to first unread message

oleg.k...@gmail.com

unread,
May 2, 2007, 9:38:24 PM5/2/07
to Haml
Well, not exactly. Observe:

>> Haml::Engine.new("%h1 header").render
=> "<h1>header</h1>\n"

Awesome, now how about

>> Haml::Engine.new("=link_to 'link', ''").render
NoMethodError: undefined method `link_to' for #<Object:0x25417b4>

Well crap. Fortunately I can do this:

>> include ActionView::Helpers::UrlHelper
=> Object
>> Haml::Engine.new("=link_to 'link', ''").render
=> "<a href=\"\">link</a>\n"

Great! Now I can load any helper I want. Super. Let's try this:

>> include ActionView::Helpers::AssetTagHelper
=> Object
>> include ActionView::Helpers::TagHelper
=> Object
>> Haml::Engine.new("=image_tag 'butts.jpg'").render
NoMethodError: You have a nil object when you didn't expect it!
The error occurred while evaluating nil.request
from (haml):1
from ./script/../config/../config/../vendor/rails/actionpack/
lib/action_view/helpers/asset_tag_helper.rb:207:in
`compute_public_path'

So that helper is using @controller variable that i don't have
instantiated. What do I do about that? I ended up commenting that line
out. (I know, bad. But it didn't break anything)

Now I have one thing to take care of. I need to be able to use my
ApplicationHelper... So

>> include ApplicationHelper
=> Object
>> Haml::Engine.new("= expedition_dates_table(8)").render
NoMethodError: undefined method `expedition_dates_table' for #<Object:
0x24bc8c0>

Well shit, Carl! Shit!

Last thing I need is to have partials working. Like

>> Haml::Engine.new("= render :partial => 'main/hallo'").render
NoMethodError: undefined method `render' for #<Object:0x2568634>

Well, that's even worse as render is part of ActionController::Base
and that's not something I can include.

Obviously I'm missing something. I normally never get so deep into
Rails' guts. But this time I kinda need to. Can somebody be so kind to
push me in the right direction. Greatly appreciated.

Nathan Weizenbaum

unread,
May 2, 2007, 11:08:15 PM5/2/07
to ha...@googlegroups.com
The trick here is that you don't want the objects included in the
context from which you're calling Haml::Engine#render... you want them
in the context in which the template is being rendered. Handily, the
render method takes an object to use as the scope as the first argument.
So what you want to do is

base = ActiveRecord::Base.new('path/to/views', {}, controller)
Haml::Engine.new(text).render(base)

And that should work just peachily.

- Nathan

oleg.k...@gmail.com

unread,
May 3, 2007, 11:20:48 AM5/3/07
to Haml
Hey Nathan,

Context thing definitely makes sense to me now. However I have
difficulty properly setting up that base variable.

So if I do

>> base = ActiveRecord::Base.new('app/views', {}, ContentController)
NameError: uninitialized constant ContentController

I have ContentController that is not tied to any model there.
Obviously I'm doing this completely wrong.

also
base = User.new doesn't really provide context that I'm looking for?
Different thing?

Thanks

Nathan Weizenbaum

unread,
May 3, 2007, 2:06:19 PM5/3/07
to ha...@googlegroups.com
The third argument to the ActionView::Base is an actual instance of a
controller. You need it to do stuff like url_for and link_to in ActionView.

The way Rails works is to render templates (both Haml and ERB) in an
ActionView instance, giving you access to all the handy helpers. You
could do it in a model like User, but then you wouldn't have access to
the helpers but would instead have access to the User's variables, which
would be weird.

- Nathan

oleg.k...@gmail.com

unread,
May 3, 2007, 3:05:58 PM5/3/07
to Haml
Ah, you confused me with ActiveRecord::Base vs ActionView::Base
thing...

I think I'm making progress:

>> base = ActionView::Base.new('/app/views/content', {}, ContentController)
=> #<ActionView::Base:0x22df37c @base_path="/app/views/content",
@controller=ContentController, @assigns_added=nil, @assigns={},
@logger=#<Logger:0x22c4e28 @level=0,
@default_formatter=#<Logger::Formatter:0x22c4c98
@datetime_format=nil>, @progname=nil, @logdev=#<Logger::LogDevice:
0x22c4bf8 @dev=#<File:script/../config/../config/../log/
development.log>, @shift_size=1048576, @shift_age=0,
@filename="script/../config/../config/../log/development.log",
@mutex=#<Logger::LogDevice::LogDeviceMutex:0x22c4b08 @mon_owner=nil,
@mon_waiting_queue=[], @mon_entering_queue=[], @mon_count=0>>,
@formatter=nil>>
>> Haml::Engine.new('= link_to "blah", "/"').render(base)
=> "<a href=\"/\">blah</a>\n"

Awesome!

But:

>> Haml::Engine.new('= image_tag "blah.gif"').render(base)
NoMethodError: undefined method `request' for ContentController:Class


from (haml):1
from ./script/../config/../config/../vendor/rails/actionpack/
lib/action_view/helpers/asset_tag_helper.rb:207:in
`compute_public_path'

Bah, Fixable if I comment that line out in that ActionView helper.

There are still problems though.

I can't use my own helper methods still:
>> Haml::Engine.new('= short_date Date.today').render(base)
NoMethodError: undefined method `short_date' for #<ActionView::Base:
0x228672c>

And I can't use partials:
>> Haml::Engine.new('= render :partial => "test"').render(base)
NoMethodError: undefined method `controller_path' for Class:Class

Still missing something :(

Thanks so much

On May 3, 2:06 pm, Nathan Weizenbaum <nex...@gmail.com> wrote:
> The third argument to the ActionView::Base is an actual instance of a
> controller. You need it to do stuff like url_for and link_to in ActionView.
>
> The way Rails works is to render templates (both Haml and ERB) in an
> ActionView instance, giving you access to all the handy helpers. You
> could do it in a model like User, but then you wouldn't have access to
> the helpers but would instead have access to the User's variables, which
> would be weird.
>
> - Nathan
>

Nathan Weizenbaum

unread,
May 3, 2007, 6:49:35 PM5/3/07
to ha...@googlegroups.com
The thing is that a lot of the helpers assume a full Rails stack, with requests being dealt with by the controller and sent off to ActionView. It's a bit of a pain to emulate everything that happens there. That's why it wants the request object in the controller, for instance.

The way to get around it is just to initialize everything the same way it's initialized by Rails. To figure out what this entails, you'll probably have to dig around in the Rails source code a little.

- Nathan

oleg.k...@gmail.com

unread,
May 4, 2007, 10:14:52 AM5/4/07
to Haml
I was afraid of that. :(

Can't believe nobody ever needed to use forms/helpers/etc in content
that is stored on database. Can't find anything at all. Guess I need
to start digging to figure out what's the difference between context
that haml engine gets during regular view renders and the one I'm
trying to feed it.

Thanks.

P.S. if anybody has any input on this it would be great.


On May 3, 6:49 pm, "Nathan Weizenbaum" <nex...@gmail.com> wrote:
> The thing is that a lot of the helpers assume a full Rails stack, with
> requests being dealt with by the controller and sent off to ActionView. It's
> a bit of a pain to emulate everything that happens there. That's why it
> wants the request object in the controller, for instance.
>
> The way to get around it is just to initialize everything the same way it's
> initialized by Rails. To figure out what this entails, you'll probably have
> to dig around in the Rails source code a little.
>
> - Nathan
>

Reply all
Reply to author
Forward
0 new messages