Forum: Ruby accessing methods from the blocks caller

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A0f5dfa39cdd53b04fafece99475dc46?d=identicon&s=25 andrew (Guest)
on 2007-03-18 06:31
(Received via mailing list)
Hello,

Sorry if this has been asked many times before, but I'm having a hard
time
finding the right keywords to search for this one.

Here's my question... if I have a method that accepts a block and I want
to
call a method of the class I'm in, in that block, how do I do it?  See
the
comment below in the example.  Should make that sentence a bit clearer.
:)

class Test
    def method1
    end

    def method2
        accept_block do # accept_block is not part of the Test class
            ...
            method1    # I want to call method1 from the class I'm in,
but
I'm getting undefined method for method1
            ...
        end
    end
end

I understand why I would be getting this error, but I don't know how to
fix
it.  Is there a way to access the caller in the block in order to access
the
method of it?  Kernel.caller is the closest I found, but it's not what I
want.

I hope this makes some sense.  The example is a bit contrived, but
hopefully
I get the point across.

Thanks,
Andrew
A0f5dfa39cdd53b04fafece99475dc46?d=identicon&s=25 andrew (Guest)
on 2007-03-18 08:56
(Received via mailing list)
Taking a better look at my pickaxe book, it seems as though this is
simply a
scoping issue that doesn't really have a solution.  I have a workaround,
but
was curious to know if there was a "proper" way to accomplish what I was
looking for.

Thanks,
Andrew

"andrew" <noname@noname.com> wrote in message
news:w44Lh.32606$zU1.24952@pd7urf1no...
8bc543795b502900b5333aea73ad5533?d=identicon&s=25 Eden Li (edenli)
on 2007-03-18 09:03
(Received via mailing list)
In the three cases I could think of, "method1" was always available to
the block.  AFAIK, the block you pass to #accept_block no matter where
it is will always be bound to the lexical context you call it in,
meaning that 'method1' will always be available unless you do
something special when you call the block.

Maybe it'll help if you list the source for #accept_block and the
exact error you're getting.

# case 1, 'accept_block' defined in a super class
class S
  def foo; yield; end
end

# case 2, 'accept_block' defined in an included module
module M
  def bar; yield; end
end

# case 3, 'accept_block' defined in some other class
class D
  def baz; yield; end
end

class C < S
  include M
  def m1; 'hi'; end
  def test_foo; foo { m1 }; end
  def test_bar; bar { m1 }; end
  def test_baz; D.new.baz { m1 }; end
end

>> c = C.new
=> #<C:0xb7c396e8>
>> c.test_foo
=> "hi"
>> c.test_bar
=> "hi"
>> c.test_baz
=> "hi"
8bc543795b502900b5333aea73ad5533?d=identicon&s=25 Eden Li (edenli)
on 2007-03-18 10:45
(Received via mailing list)
$ irb
irb(main):001:0> class Test; def method1; end; def method2;
accept_block { method1 }; end; end
=> nil
irb(main):002:0> def accept_block; yield; end
=> nil
irb(main):003:0> Test.new.method2
=> nil

No error... there's something weird going on with your version of
#accept_block.  Care to dump the source out here?
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-03-18 11:30
(Received via mailing list)
On Sun, Mar 18, 2007 at 02:30:04PM +0900, andrew wrote:
>     end
> end
>
> I understand why I would be getting this error, but I don't know how to fix
> it.  Is there a way to access the caller in the block in order to access the
> method of it?  Kernel.caller is the closest I found, but it's not what I
> want.

As people have said, this *should* work. Post a complete example where
it
fails, and the error message.

Having said that, if there is a need to, the current object is called
'self'
and can be passed around explicitly if you wish:

class Test
  def accept_block(some_object)
    yield some_object
  end

  def method1
    puts "whoo!"
  end

  def method2
    accept_block(self) do |s|
      # ...
      s.method1
      # ...
    end
  end
end
Test.new.method2   # prints "whoo!"

---- But this particular example works without:

class Test
  def accept_block
    yield
  end

  def method1
    puts "whoo!"
  end

  def method2
    accept_block do
      # ...
      method1
      # ...
    end
  end
end
Test.new.method2   # prints "whoo!"

Regards,

Brian.
A0f5dfa39cdd53b04fafece99475dc46?d=identicon&s=25 andrew (Guest)
on 2007-03-18 21:22
(Received via mailing list)
I'm experiencing the issue using Rails.  I wanted to leave mention of
Rails
out of my post as I figured it was simply a Ruby issue, but perhaps not.

class MyController < ApplicationController
    def some_action
        render :update do |page|
            render_to_string        # getting an error that
render_to_string
is undefined
        end
    end
end

I fix this by doing this...
def some_action
    str = render_to_string
    render :update to |page|
        # use str in the block
    end
end

So for anybody with a bit of rails knowledge, do you know what's going
on?
I can ask this in a rails group now if you think it's off topic.

Thanks again,
Andrew

"eden li" <eden.li@gmail.com> wrote in message
news:1174204947.155558.226150@d57g2000hsg.googlegroups.com...
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-03-18 21:41
(Received via mailing list)
On Mon, Mar 19, 2007 at 05:20:05AM +0900, andrew wrote:
> end
>
> I fix this by doing this...
> def some_action
>     str = render_to_string
>     render :update to |page|
>         # use str in the block
>     end
> end

This is a rails issue. The *controller* and the *view* are two separate
objects; methods defined in the controller are not by default available
in
the view.

The preferred solution is usually to define render_to_string as a helper
in
app/helpers/mys.rb (as long as it's needed only by the view, not by the
controller itself)

If you must define it in the controller for some reason, then you can
make
it available in the view by

    def render_to_string
      ...
    end
    helper_method :render_to_string

> I can ask this in a rails group now if you think it's off topic.

It's definitely a rails issue - further questions would best be asked
there.

Regards,

Brian.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-03-18 21:57
(Received via mailing list)
On Mon, Mar 19, 2007 at 05:40:45AM +0900, Brian Candler wrote:
>
>     def render_to_string
>       ...
>     end
>     helper_method :render_to_string

Alternatively: I think that *public* methods in the controller can be
accessed from within the view by using the 'controller' accessor. e.g.

<%= controller.render_to_string %>

But this is probably not a good idea if render_to_string is a method
which
you don't want to make available to the outside world (in which case you
should mark it 'private')

B.
This topic is locked and can not be replied to.