Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Store erb block and alter scope of erb block eval?

Reply
Thread Tools

Store erb block and alter scope of erb block eval?

 
 
Steve V
Guest
Posts: n/a
 
      04-18-2005
I tried posting this in the Rails list, and didn't get any responses, so
maybe there's someone here that can help me with my problem.

I'm trying to modularize some display functionality within my Rails app. I
need to be able to store an erb block, and then evaluate it 1 or more times
at a later point in time. Two questions here, which are driving me crazy!

1) How can I store an erb block captured using do for later use? Regular
variable assignment doesn't appear to work.

def content(&block)
@raw_content = block
end

The above does not work. However, if I evaluate 'block' within the content
method call, then the evaluation works. If I try to evaluate @raw_content at
a later point through another function it just returns nothing. So how
exactly do I store 'block' for later use?

2) When evaluating 'block', how can I get it to use the variables present
within the scope of the calling function, or at least within the calling
class? As it stands now, it will only take variables that have been defined
in the controller, and not my class.

rhtml file
<%r = Renderer.new()
r.content do%>
<%=@sometext%>
<%end%>
<%=r.render()%>

rb file
class SomeController < ApplicationController
def blah()
@sometext = "blah"
end
end

class Renderer
def content(&block)
@sometext = "content"
buffer = eval("_erbout", block.binding);
pos = buffer.length
block.call

@data = buffer[pos..-1]

buffer[pos..-1] = ""
end

def render()
@data
end
end

The above will render "blah", and not "content", even if the definition of
@sometext is removed from the controller, the eval will not take from the
class.

Any help would be greatly appreciated.

Thanks,
Steve




 
Reply With Quote
 
 
 
 
Gavin Kistner
Guest
Posts: n/a
 
      04-19-2005
On Apr 18, 2005, at 3:54 PM, Steve V wrote:
> 1) How can I store an erb block captured using do for later use?
> Regular
> variable assignment doesn't appear to work.


Works for me:

class Foo
def set_block( &block ); @meth = block; end
def call_block( *args ); @meth.call( *args ); end
end

f = Foo.new
f.set_block { |x,y| p x,y }
f.call_block 3,4
#=>3
#=>4


> 2) When evaluating 'block', how can I get it to use the variables
> present
> within the scope of the calling function, or at least within the
> calling
> class?


require 'erb'

class Foo
def rhtml=( str )
@rhtml = ERB.new( str )
end
def run1
localvar = 'run1'
@rhtml.result( binding )
end
def run2
localvar = 'run2'
@rhtml.result( binding )
end
end

f = Foo.new
f.rhtml = '<p><%= localvar %></p>'
p f.run1
#=> "<p>run1</p>"
p f.run2
#=> "<p>run2</p>"



 
Reply With Quote
 
 
 
 
Steve V
Guest
Posts: n/a
 
      04-19-2005

> Works for me:
>
> class Foo
> def set_block( &block ); @meth = block; end
> def call_block( *args ); @meth.call( *args ); end
> end
>
> f = Foo.new
> f.set_block { |x,y| p x,y }
> f.call_block 3,4
> #=>3
> #=>4


>
> > 2) When evaluating 'block', how can I get it to use the variables
> > present
> > within the scope of the calling function, or at least within the
> > calling
> > class?

>
> require 'erb'
>
> class Foo
> def rhtml=( str )
> @rhtml = ERB.new( str )
> end
> def run1
> localvar = 'run1'
> @rhtml.result( binding )
> end
> def run2
> localvar = 'run2'
> @rhtml.result( binding )
> end
> end
>
> f = Foo.new
> f.rhtml = '<p><%= localvar %></p>'
> p f.run1
> #=> "<p>run1</p>"
> p f.run2
> #=> "<p>run2</p>"
>


Is there something special erb does when you capture a block from an rhtml
page? I tried passing my own variable values to the block within my
class(separate from the controller), and the values are ignored. I think the
heart of the problem is that you're calling ERB.new on a regular string. I
need to capture this information from an rhtml page. The only way I have
found to do that is by using a "do" block.

r.content do%>
Test <%=@sometext%>
<%end%>

This gives me a block, and not a string. Is there a way to turn the contents
of the returned proc as a string? to_s just gives me the memory location(?)
of the proc object.

The other question is why aren't my variables used for the block call when
I'm in the class? Does it have something to do with the existing scope of
the proc object? Can I change the scope? The only place I can get that
@sometext value to be used from is within the controller. I have tried
defining @sometext within my separate class, and passing that into the call,
but nothing happens.

def content(&block)
@sometext = "sometext"
@data = block.call(@sometext)
end

def render()
return @data
end

The above will just render "Test ", and not use the specified value for
@sometext.

Steve




 
Reply With Quote
 
Steve V
Guest
Posts: n/a
 
      04-19-2005

> Is there something special erb does when you capture a block from an rhtml
> page? I tried passing my own variable values to the block within my
> class(separate from the controller), and the values are ignored.
> I think the
> heart of the problem is that you're calling ERB.new on a regular string. I
> need to capture this information from an rhtml page. The only way I have
> found to do that is by using a "do" block.
>
> r.content do%>
> Test <%=@sometext%>
> <%end%>
>
> This gives me a block, and not a string. Is there a way to turn
> the contents
> of the returned proc as a string? to_s just gives me the memory
> location(?)
> of the proc object.
>
> The other question is why aren't my variables used for the block call when
> I'm in the class? Does it have something to do with the existing scope of
> the proc object? Can I change the scope? The only place I can get that
> @sometext value to be used from is within the controller. I have tried
> defining @sometext within my separate class, and passing that
> into the call,
> but nothing happens.
>
> def content(&block)
> @sometext = "sometext"
> @data = block.call(@sometext)
> end
>
> def render()
> return @data
> end
>
> The above will just render "Test ", and not use the specified value for
> @sometext.


After some more experimenting, I have made a little more progress, but I'm
still not able to use a compiled ERB template.

<%r.data = %q{%>
So close! <%=blah%>
<%}%>

The above rhtml code will get me a string into my class, but it isn't
"\t\tSo close! <%=blah%>\n\t" as expected. Instead it is what appears to be
some type of parsed string: "; _erbout.concat "\n" _erbout.concat "\t\tSo
close! "; _erbout.concat((@blah).to_s); _erbout.concat "\n" _erbout.concat
"\t"; "

I can use eval() on the above, with the binding of the working class which
sort of solves the problem. Can anyone tell me what piece I'm missing here
to keep the code suitable for loading into an ERB template?

Thanks,
Steve




 
Reply With Quote
 
Gavin Kistner
Guest
Posts: n/a
 
      04-20-2005
On Apr 18, 2005, at 8:56 PM, Steve V wrote:
> Is there something special erb does when you capture a block from an
> rhtml
> page? I tried passing my own variable values to the block within my
> class(separate from the controller), and the values are ignored. I
> think the
> heart of the problem is that you're calling ERB.new on a regular
> string. I
> need to capture this information from an rhtml page.


Can you be more specific about what you are doing? I don't understand
what you mean by "capture a block from an rhtml page".

Could you provide your full code showing the problem you are having?

(I'm not an ERb expert, so I'm probably missing some way of using it
that I've not seen before.)
--
"When I am working on a problem I never think about beauty. I only
think about how to solve the problem. But when I have finished, if the
solution is not beautiful, I know it is wrong."
- R. Buckminster Fuller



 
Reply With Quote
 
Steve V
Guest
Posts: n/a
 
      04-20-2005

>
> Can you be more specific about what you are doing? I don't understand
> what you mean by "capture a block from an rhtml page".
>
> Could you provide your full code showing the problem you are having?
>
> (I'm not an ERb expert, so I'm probably missing some way of using it
> that I've not seen before.)


Hmm, okay. As you will see from using the below. The <%=@title%> value will
only be taken from the value in the TestController. No matter what I do, I
cannot get the @title variable set in the TableBuilder class to be the one
that is used.

Steve

test.rhtml:
<%tb = TableBuilder.new("Table Title")
tb.header_template do%>
This is the header template <%=@title%>
<%end%>
<%=tb.render()%>

test_controller.rb:
class TestController < ApplicationController
def test()
#uncomment, and the title variable will
# be used in the template
#@title = "controller title"
end
end

class TableBuilder

def initialize(title = "")
@title = title
end

def header_template(&block)
@headerTemplate = block

end

def render()
out = ""

#do table building stuff.
_erbout = ""
#the below is taken from capture_helper.rb in
# rails action_view\helpers
buffer = eval("_erbout", @headerTemplate)
pos = buffer.length
@headerTemplate.call(binding)

out << buffer[pos..-1]
buffer[pos..-1] = ""

#do other table building stuff

return out
end
end




 
Reply With Quote
 
Steve V
Guest
Posts: n/a
 
      04-20-2005
> Hmm, okay. As you will see from using the below. The <%=@title%>
> value will
> only be taken from the value in the TestController. No matter what I do, I
> cannot get the @title variable set in the TableBuilder class to be the one
> that is used.


The primary goal of this all is to be able to use the variable from the
object scope other than the controller. The secondary goal is to be able to
cache a precompiled template. The method above gets me a proc object(I
think). If that is the case, are procs already compiled, or do they need to
be compiled at the time of execution? I wanted to store these as ERB
templates so that I could take advantage of caching them in a compiled
state. But if the procs are already compiled and there is a way to cache
them, then that would work as well.

Steve




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
link to .erb file, from .erb file Dan Thomas Ruby 4 01-26-2011 09:26 PM
Alter - Perl extension for Alter Ego Objects anno4000@radom.zrz.tu-berlin.de Perl Misc 0 06-30-2007 04:13 PM
How can I alter the datatype of the data quiry from a database and store it into a gridview? khoaha@gmail.com ASP .Net Web Controls 1 10-06-2006 04:40 AM
erb and scope Wybo Dekker Ruby 6 12-11-2005 04:22 PM
How do namespace scope and class scope differ? Steven T. Hatton C++ 9 07-19-2005 06:07 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57