why can't an instance instantiated within a class method access aprotected instance method?

Discussion in 'Ruby' started by Greg Hauptmann, Jun 15, 2008.

  1. [Note: parts of this message were removed to make it a legal post.]

    Hi,
    Why can't an instance instantiated within a class method access a protected
    instance method?

    e.g.

    class Recurring < ActiveRecord::Base
    def self.reconcile t = Transaction.find:)first)
     
    Greg Hauptmann, Jun 15, 2008
    #1
    1. Advertising

  2. Re: why can't an instance instantiated within a class method accessa protected instance method?

    [Note: parts of this message were removed to make it a legal post.]

    (complete email)Hi,

    Why can't an instance instantiated within a class method access a protected
    instance method?

    e.g.

    class Recurring < ActiveRecord::Base

    def self.reconcile rs = Recurring.find:)all)
    rs.each do |r|
    r.reconcile_one
    end
    end

    protected

    def reconcile_one
    # do something
    end

    end
     
    Greg Hauptmann, Jun 15, 2008
    #2
    1. Advertising

  3. Re: why can't an instance instantiated within a class method accessa protected instance method?

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1


    On Jun 15, 2008, at 12:37 PM, Greg Hauptmann wrote:

    > (complete email)Hi,
    >
    > Why can't an instance instantiated within a class method access a
    > protected
    > instance method?
    >
    > e.g.
    >
    > class Recurring < ActiveRecord::Base
    >
    > def self.reconcile rs = Recurring.find:)all)
    > rs.each do |r|
    > r.reconcile_one
    > end
    > end
    >
    > protected
    >
    > def reconcile_one
    > # do something
    > end
    >
    > end


    Because calling a Method with an explicit receiver is like "calling
    from the outside".

    Regards,
    Florian Gilcher
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.8 (Darwin)

    iEYEARECAAYFAkhVCkAACgkQJA/zY0IIRZafKQCghgHXBhTmfp3eCYVWTbQempIp
    EwcAoJqNwn9FkHgTZjt9/jc14+PeD0A5
    =nITW
    -----END PGP SIGNATURE-----
     
    Florian Gilcher, Jun 15, 2008
    #3
  4. Re: why can't an instance instantiated within a class method accessa protected instance method?

    Hi --

    On Sun, 15 Jun 2008, Florian Gilcher wrote:

    > -----BEGIN PGP SIGNED MESSAGE-----
    > Hash: SHA1
    >
    >
    > On Jun 15, 2008, at 12:37 PM, Greg Hauptmann wrote:
    >
    >> (complete email)Hi,
    >>
    >> Why can't an instance instantiated within a class method access a protected
    >> instance method?
    >>
    >> e.g.
    >>
    >> class Recurring < ActiveRecord::Base
    >>
    >> def self.reconcile rs = Recurring.find:)all)
    >> rs.each do |r|
    >> r.reconcile_one
    >> end
    >> end
    >>
    >> protected
    >>
    >> def reconcile_one
    >> # do something
    >> end
    >>
    >> end

    >
    > Because calling a Method with an explicit receiver is like "calling from the
    > outside".


    It's not quite that. Protected methods can be called with an explicit
    receiver, but they can only be called on objects that are of the same
    class as self (or a subclass thereof). In self.reconcile, self is
    Recurring, and therefore of class Class, while rs is of class
    Recurring.


    David

    --
    Rails training from David A. Black and Ruby Power and Light:
    ADVANCING WITH RAILS June 16-19 Berlin
    ADVANCING WITH RAILS July 21-24 Edison, NJ
    See http://www.rubypal.com for details and updates!
     
    David A. Black, Jun 15, 2008
    #4
  5. Re: why can't an instance instantiated within a class method accessa protected instance method?

    [Note: parts of this message were removed to make it a legal post.]

    On Sun, Jun 15, 2008 at 11:03 PM, David A. Black <> wrote:

    > Hi --
    > On Sun, 15 Jun 2008, Florian Gilcher wrote:
    >
    > -----BEGIN PGP SIGNED MESSAGE-----
    >> Hash: SHA1
    >>
    >>
    >> On Jun 15, 2008, at 12:37 PM, Greg Hauptmann wrote:
    >>
    >> (complete email)Hi,
    >>>
    >>> Why can't an instance instantiated within a class method access a
    >>> protected
    >>> instance method?
    >>>
    >>> e.g.
    >>>
    >>> class Recurring < ActiveRecord::Base
    >>>
    >>> def self.reconcile rs = Recurring.find:)all)
    >>> rs.each do |r|
    >>> r.reconcile_one
    >>> end
    >>> end
    >>>
    >>> protected
    >>>
    >>> def reconcile_one
    >>> # do something
    >>> end
    >>>
    >>> end
    >>>

    >>
    >> Because calling a Method with an explicit receiver is like "calling from
    >> the outside".
    >>

    >
    > It's not quite that. Protected methods can be called with an explicit
    > receiver, but they can only be called on objects that are of the same
    > class as self (or a subclass thereof). In self.reconcile, self is
    > Recurring, and therefore of class Class, while rs is of class
    > Recurring.
    >
    >
    > David



    Thanks - can I ask:
    (a) what do you mean by "explicit" - just to understand
    (b) is there a way I can adjust my code so that I can leave methods like
    "reconcile_one" private or protected, i.e. not really to be available to the
    outside world (except in this case where I'm calling it from with an
    instance of the class really, but it's just the logistics of Ruby that isn't
    allowing it to work...if I've understood things correctly)

    Greg
     
    Greg Hauptmann, Jun 15, 2008
    #5
  6. Re: why can't an instance instantiated within a class method accessa protected instance method?

    On 15.06.2008 15:17, Greg Hauptmann wrote:
    > Thanks - can I ask:


    Guess so.

    > (a) what do you mean by "explicit" - just to understand


    no_explicit_receiver()
    self.has_explicit_receiver()

    > (b) is there a way I can adjust my code so that I can leave methods like
    > "reconcile_one" private or protected, i.e. not really to be available to the
    > outside world (except in this case where I'm calling it from with an
    > instance of the class really, but it's just the logistics of Ruby that isn't
    > allowing it to work...if I've understood things correctly)


    You can use #send or #instance_eval, e.g.

    irb(main):001:0> class F
    irb(main):002:1> protected
    irb(main):003:1> def x;1 end
    irb(main):004:1> end
    => nil
    irb(main):005:0> f=F.new
    => #<F:0x7ff94460>
    irb(main):006:0> f.x
    NoMethodError: protected method `x' called for #<F:0x7ff94460>
    from (irb):6
    from :0
    irb(main):007:0> f.instance_eval { x }
    => 1
    irb(main):008:0> f.send :x
    => 1
    irb(main):009:0>

    Cheers

    robert
     
    Robert Klemme, Jun 15, 2008
    #6
  7. Re: why can't an instance instantiated within a class method accessa protected instance method?

    [Note: parts of this message were removed to make it a legal post.]

    On Sun, Jun 15, 2008 at 11:29 PM, Robert Klemme <>
    wrote:

    > On 15.06.2008 15:17, Greg Hauptmann wrote:
    >
    >> Thanks - can I ask:
    >>

    >
    > Guess so.
    >
    > (a) what do you mean by "explicit" - just to understand
    >>

    >
    > no_explicit_receiver()
    > self.has_explicit_receiver()
    >
    > (b) is there a way I can adjust my code so that I can leave methods like
    >> "reconcile_one" private or protected, i.e. not really to be available to
    >> the
    >> outside world (except in this case where I'm calling it from with an
    >> instance of the class really, but it's just the logistics of Ruby that
    >> isn't
    >> allowing it to work...if I've understood things correctly)
    >>

    >
    > You can use #send or #instance_eval, e.g.
    >
    > irb(main):001:0> class F
    > irb(main):002:1> protected
    > irb(main):003:1> def x;1 end
    > irb(main):004:1> end
    > => nil
    > irb(main):005:0> f=F.new
    > => #<F:0x7ff94460>
    > irb(main):006:0> f.x
    > NoMethodError: protected method `x' called for #<F:0x7ff94460>
    > from (irb):6
    > from :0
    > irb(main):007:0> f.instance_eval { x }
    > => 1
    > irb(main):008:0> f.send :x
    > => 1
    > irb(main):009:0>
    >
    > Cheers
    >
    > robert
    >


    Thanks Robert - do you understand why Ruby allows the "send :x" method to
    work here, but not the ".x" out of curiosity? Does this make sense to
    people it should do this?
    Greg
     
    Greg Hauptmann, Jun 15, 2008
    #7
  8. Re: why can't an instance instantiated within a class method accessa protected instance method?

    Hi --

    On Sun, 15 Jun 2008, Greg Hauptmann wrote:

    > On Sun, Jun 15, 2008 at 11:29 PM, Robert Klemme <>
    > wrote:
    >
    >> On 15.06.2008 15:17, Greg Hauptmann wrote:
    >>
    >>> Thanks - can I ask:
    >>>

    >>
    >> Guess so.
    >>
    >> (a) what do you mean by "explicit" - just to understand
    >>>

    >>
    >> no_explicit_receiver()
    >> self.has_explicit_receiver()
    >>
    >> (b) is there a way I can adjust my code so that I can leave methods like
    >>> "reconcile_one" private or protected, i.e. not really to be available to
    >>> the
    >>> outside world (except in this case where I'm calling it from with an
    >>> instance of the class really, but it's just the logistics of Ruby that
    >>> isn't
    >>> allowing it to work...if I've understood things correctly)
    >>>

    >>
    >> You can use #send or #instance_eval, e.g.
    >>
    >> irb(main):001:0> class F
    >> irb(main):002:1> protected
    >> irb(main):003:1> def x;1 end
    >> irb(main):004:1> end
    >> => nil
    >> irb(main):005:0> f=F.new
    >> => #<F:0x7ff94460>
    >> irb(main):006:0> f.x
    >> NoMethodError: protected method `x' called for #<F:0x7ff94460>
    >> from (irb):6
    >> from :0
    >> irb(main):007:0> f.instance_eval { x }
    >> => 1
    >> irb(main):008:0> f.send :x
    >> => 1
    >> irb(main):009:0>
    >>
    >> Cheers
    >>
    >> robert
    >>

    >
    > Thanks Robert - do you understand why Ruby allows the "send :x" method to
    > work here, but not the ".x" out of curiosity? Does this make sense to
    > people it should do this?


    Private and protected are really only advisory, since you can in fact
    always get around them. The idea is to have the most common
    method-calling technique (the dot) respect them, so that if you want
    to get around them, you have to make a point of using one of the other
    techniques.


    David

    --
    Rails training from David A. Black and Ruby Power and Light:
    ADVANCING WITH RAILS June 16-19 Berlin
    ADVANCING WITH RAILS July 21-24 Edison, NJ
    See http://www.rubypal.com for details and updates!
     
    David A. Black, Jun 15, 2008
    #8
  9. Greg Hauptmann

    J. Cooper Guest

    Re: why can't an instance instantiated within a class method


    >> Thanks Robert - do you understand why Ruby allows the "send :x" method to
    >> work here, but not the ".x" out of curiosity? Does this make sense to
    >> people it should do this?


    The whole point of the private/protected method deal is to prevent what
    you are trying to do :) Ruby, having lots of metaprogramming
    capabilities, lets you get around this "if you really know what you are
    doing" -- as you can see, it's a bit more of a pain then just the
    standard way of calling a method. It's to help keep you honest.

    --
    Posted via http://www.ruby-forum.com/.
     
    J. Cooper, Jun 15, 2008
    #9
  10. Greg Hauptmann

    Loren Segal Guest

    Re: why can't an instance instantiated within a class method accessa protected instance method?

    > Does this make sense to people it should do this?

    Should people use send() to get around protected method visibility? No.

    Do they? Yes.

    Is it justified? Sometimes it is, sometimes it isn't.

    Having to send() to get around a visibility issue usually implies that
    there's some API design problem in the code you're using. The reason its
    usage is sometimes justified is simply because you don't own everybody
    else's code and you can't be held liable for their mistakes. There's
    also the case where you simply have no other choice.

    I think in this scenario you really need to ask yourself why the method
    is protected to begin with. I see nothing in your code that would have
    me believe that your `self.reconcile` method *must* come from the
    metaclass of the object. In fact, it looks like a factory method that
    could ideally be called from anywhere. That to me constitutes public
    method, especially since what's really happening is: "grab a bunch of
    objects and call `reconcile_once` on them"... I see no reason why some
    fictional `MyOtherClass` wouldn't be able to do the same thing with your
    objects.

    Loren
    --
    Posted via http://www.ruby-forum.com/.
     
    Loren Segal, Jun 16, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    8
    Views:
    423
    Guest
    Oct 14, 2004
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,998
    Smokey Grindel
    Dec 2, 2006
  3. Dev
    Replies:
    8
    Views:
    670
  4. Replies:
    3
    Views:
    931
    Roedy Green
    Jan 28, 2008
  5. Replies:
    0
    Views:
    641
Loading...

Share This Page