Erb: terminating a script?

In PHP I can do the following:

  A<br>
  B<br>
  <?php exit; ?>
  C<br>
  D<br>

This results in the following data showing up on the page:

  A
  B

I want to do something similar in Erb:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

Thanks in advance.

···

--
Lloyd Zusman
ljz@asfast.com

Just doing some quick reading, you may want to try exit or exit!, if
you haven't already. If you have, what happened? Did it still output C
and D?

Apparently they're very similar, however, exit! ignores exception
handling, at_exit functions, and finalizers.

···

On Wed, 2 Mar 2005 21:32:28 +0900, Lloyd Zusman <ljz@asfast.com> wrote:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

Here's a bizzare idea ...

<% callcc do |quit_early| %>
A<br>
B<br>
<% quit_early.call %>
C<br>
D<br>
<% end %>

Does that work?

···

On Wednesday 02 March 2005 07:32 am, Lloyd Zusman wrote:

I want to do something similar in Erb:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

William Ramirez Wrote:

> A<br>
> B<br>
> <% WHAT GOES HERE TO END THE SCRIPT? %>
> C<br>
> D<br>
>
> What do use for "WHAT GOES HERE ..." in order to cause the
> processing to end after A and B print out?

Just doing some quick reading, you may want to try exit or exit!, if
you haven't already. If you have, what happened? Did it still output C
and D?

Apparently they're very similar, however, exit! ignores exception
handling, at_exit functions, and finalizers.

I did call exit, and it terminated the entire web server. I forgot to
mention that I'm running Erb inside of ErbHandler within a webrick
FileHandler instance, not within a stand-alone CGI. I'm sorry for
having left out that key piece of information in my original query.

The same thing happened with the "exit!" method.

What I'm looking for is something that can be invoked within
Erb#result which will terminate the eval at the point at which it
occurs, but which will allow information up to that point to still
appear in the output.

Does such a thing even exist?

If not, I can hack or subclass ErbHandler to enclose its generated
code within a "catch" block inside Erb#result, and then create a
method that I can call which will do an appropriate "throw" if I
want to terminate the processing. But before I embark on that
journey, I want to see if something that has this effect has
already been invented.

···

On Wed, 2 Mar 2005 21:32:28 +0900, Lloyd Zusman <ljz@asfast.com> wrote:

--
Lloyd Zusman
ljz@asfast.com

Jim Weirich <jim@weirichhouse.org> writes:

···

On Wednesday 02 March 2005 07:32 am, Lloyd Zusman wrote:

I want to do something similar in Erb:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

Here's a bizzare idea ...

<% callcc do |quit_early| %>
A<br>
B<br>
<% quit_early.call %>
C<br>
D<br>
<% end %>

Does that work?

Yes, it does work.

I still like the lambda-call thing I mentioned in my previous message,
because using 'break' and 'return' seem to me to be more natural to use.

But this is a good idea, also. Thanks.

--
Lloyd Zusman
ljz@asfast.com
God bless you.

William Ramirez Wrote:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

Just doing some quick reading, you may want to try exit or exit!, if
you haven't already. If you have, what happened? Did it still output C
and D?

Apparently they're very similar, however, exit! ignores exception
handling, at_exit functions, and finalizers.

I did call exit, and it terminated the entire web server. I forgot to
mention that I'm running Erb inside of ErbHandler within a webrick
FileHandler instance, not within a stand-alone CGI. I'm sorry for
having left out that key piece of information in my original query.

The same thing happened with the "exit!" method.

Have you tried doing 'return'? Or perhaps 'break'? I haven't tried these myself, so I don't know if they will work or not. Just throwing out some ideas.

- Jamis

···

On Mar 2, 2005, at 12:19 PM, Lloyd Zusman wrote:

On Wed, 2 Mar 2005 21:32:28 +0900, Lloyd Zusman <ljz@asfast.com> >> wrote:

What I'm looking for is something that can be invoked within
Erb#result which will terminate the eval at the point at which it
occurs, but which will allow information up to that point to still
appear in the output.

Does such a thing even exist?

If not, I can hack or subclass ErbHandler to enclose its generated
code within a "catch" block inside Erb#result, and then create a
method that I can call which will do an appropriate "throw" if I
want to terminate the processing. But before I embark on that
journey, I want to see if something that has this effect has
already been invented.

--
Lloyd Zusman
ljz@asfast.com

Jamis Buck <jamis_buck@byu.edu> writes:

William Ramirez Wrote:

  A<br>
  B<br>
  <% WHAT GOES HERE TO END THE SCRIPT? %>
  C<br>
  D<br>

What do use for "WHAT GOES HERE ..." in order to cause the
processing to end after A and B print out?

Just doing some quick reading, you may want to try exit or exit!, if
you haven't already. If you have, what happened? Did it still output C
and D?

Apparently they're very similar, however, exit! ignores exception
handling, at_exit functions, and finalizers.

I did call exit, and it terminated the entire web server. I forgot to
mention that I'm running Erb inside of ErbHandler within a webrick
FileHandler instance, not within a stand-alone CGI. I'm sorry for
having left out that key piece of information in my original query.

The same thing happened with the "exit!" method.

Have you tried doing 'return'? Or perhaps 'break'? I haven't tried these
myself, so I don't know if they will work or not. Just throwing out some
ideas.

Yes, I have tried them.

Using 'return', I get this error:

  ERROR ThreadError: return can't jump across threads

Using 'break', I get this one:

  undefined method `result' for #<String:0x850bddc>

However, following up on the idea I mentioned in my previous message, I
did the following ... and it works:

  Original line in ErbHandler#do_GET ...

    res.body = evaluate(ERB.new(data), req, res)

  Replaced with ...

    res.body = evaluate(ERB.new('<% catch(:quit) { %>' +
                                data +
                                '<% } %>'), req, res)

Then, I can exit by doing a '<% throw :quit %>' from anywhere in the
page. And any text that's specified before the 'throw' appears in the
resulting text.

The following also yields the same results:

    res.body = evaluate(ERB.new('<% lambda { %>' + data + '<% }.call %>')
                        req, res)

In this case, I can exit early by using either '<% break %>' or
'<% return %>'. I like this one better, and this is what I have
just now implemented in my application.

Because of this, it seems to me that it would be beneficial if Erb were
to always put a lambda-call block around the text that gets evaluated.

I'm in favor of this enhancement going into a subsequent release, and
I'll soon submit a patch.

Thoughts or opinions?

···

On Mar 2, 2005, at 12:19 PM, Lloyd Zusman wrote:

On Wed, 2 Mar 2005 21:32:28 +0900, Lloyd Zusman <ljz@asfast.com> >>> wrote:

--
Lloyd Zusman
ljz@asfast.com
God bless you.

Have you tried doing 'return'? Or perhaps 'break'? I haven't tried these
myself, so I don't know if they will work or not. Just throwing out some
ideas.

[snip]

  Original line in ErbHandler#do_GET ...

    res.body = evaluate(ERB.new(data), req, res)

  Replaced with ...

    res.body = evaluate(ERB.new('<% catch(:quit) { %>' +
                                data +
                                '<% } %>'), req, res)

Then, I can exit by doing a '<% throw :quit %>' from anywhere in the
page. And any text that's specified before the 'throw' appears in the
resulting text.

The following also yields the same results:

    res.body = evaluate(ERB.new('<% lambda { %>' + data + '<% }.call %>')
                        req, res)

In this case, I can exit early by using either '<% break %>' or
'<% return %>'. I like this one better, and this is what I have
just now implemented in my application.

Excellent work, Lloyd. Thanks for sharing!

Because of this, it seems to me that it would be beneficial if Erb were
to always put a lambda-call block around the text that gets evaluated.

I'm in favor of this enhancement going into a subsequent release, and
I'll soon submit a patch.

Thoughts or opinions?

I'd vote for it. :slight_smile:

- Jamis

···

On Mar 2, 2005, at 4:02 PM, Lloyd Zusman wrote:

Jamis Buck <jamis_buck@byu.edu> writes:

[ ... ]
    res.body = evaluate(ERB.new('<% lambda { %>' +
                                data +
                                '<% }.call %>'),
                        req, res)

In this case, I can exit early by using either '<% break %>' or
'<% return %>'. I like this one better, and this is what I have
just now implemented in my application.

Excellent work, Lloyd. Thanks for sharing!

Well, I'm just glad to have found a solution, and I hope that it's
helpful to others.

Because of this, it seems to me that it would be beneficial if Erb were
to always put a lambda-call block around the text that gets evaluated.

I'm in favor of this enhancement going into a subsequent release, and
I'll soon submit a patch.

Thoughts or opinions?

I'd vote for it. :slight_smile:

OK. Here it is. Unless or until this becomes a bona-fide Erb
enhancement, just put this code snippet in your application, somewhere
after the "require 'erb'" statement:

class ERB
  def result(b=TOPLEVEL_BINDING)
    # Enclosing the 'eval' in a 'lambda-call' block allows it
    # to be cut short by means of a 'break' or 'return'.
    if @safe_level
      th = Thread.start {
        $SAFE = @safe_level
        lambda {
          eval(@src, b, (@filename || '(erb)'), 1)
        }.call
      }
      return th.value
    else
      return lambda {
        eval(@src, b, (@filename || '(erb)'), 1)
      }.call
    end
  end
end

···

On Mar 2, 2005, at 4:02 PM, Lloyd Zusman wrote:

--
Lloyd Zusman
ljz@asfast.com
God bless you.