Getting around access control

i know there is a way to do this - but how

   class C
   protected
     def meth
       42
     end
   end

   c = C::new

   c.instance_eval{ p meth }

this throws an error, of course, but i'm too tired to remember how to work
around it.

-a

···

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

Ara.T.Howard wrote:

i know there is a way to do this - but how

  class C
  protected
    def meth
      42
    end
  end

  c = C::new

  c.instance_eval{ p meth }

this throws an error, of course, but i'm too tired to remember how to work
around it.

-a

These are probably not helpful:

irb(main):012:0> c.instance_eval{ p send(:meth) }
42
=> nil
irb(main):013:0> c.instance_eval " p meth "
42
=> nil

The strange thing is that s/protected/private/ avoids the error:

irb(main):014:0> class C
irb(main):015:1> private
irb(main):016:1> def m2; 43; end
irb(main):017:1> end
=> nil
irb(main):018:0> c.instance_eval{ p m2 }
43

(ruby-1.8.2, anyway)

The original error (in the protected case) seem uncalled for....

···

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hi,

At Tue, 6 Dec 2005 16:04:39 +0900,
Ara.T.Howard wrote in [ruby-talk:169057]:

   c.instance_eval{ p meth }

this throws an error, of course, but i'm too tired to remember how to work
around it.

Hmmm, it seems to have changed unintentionally, together with
rb_funcall2(), at Dec 1. Should I fix it?

Index: eval.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.616.2.135
diff -U2 -p -u -r1.616.2.135 eval.c
--- eval.c 30 Nov 2005 15:51:05 -0000 1.616.2.135
+++ eval.c 6 Dec 2005 08:46:32 -0000
@@ -5901,11 +5901,11 @@ rb_call(klass, recv, mid, argc, argv, sc
     }

- if (mid != missing && scope == 0) {
+ if (mid != missing) {
   /* receiver specified form for private method */
- if (noex & NOEX_PRIVATE)
+ if ((noex & NOEX_PRIVATE) && && scope == 0)
       return method_missing(recv, mid, argc, argv, CSTAT_PRIV);

   /* self must be kind of a specified form for protected method */
- if (noex & NOEX_PROTECTED) {
+ if ((noex & NOEX_PROTECTED) && scope < 3) {
       VALUE defined_class = klass;

--
Nobu Nakada

yeah - it's quite strange. unfortunately the 'send' approach won't work
because the actual usage is something like

   class Controller
     def method
       handler = Handler::new self
       handler.encode '42'
     end
   end

   class Handler
     def initialize controller
       @controller = controller
     end
     def encode msg
       @controller.instance_eval do

···

On Tue, 6 Dec 2005, Joel VanderWerf wrote:

These are probably not helpful:

irb(main):012:0> c.instance_eval{ p send(:meth) }
42
=> nil
irb(main):013:0> c.instance_eval " p meth "
42
=> nil

The strange thing is that s/protected/private/ avoids the error:

irb(main):014:0> class C
irb(main):015:1> private
irb(main):016:1> def m2; 43; end
irb(main):017:1> end
=> nil
irb(main):018:0> c.instance_eval{ p m2 }
43

(ruby-1.8.2, anyway)

The original error (in the protected case) seem uncalled for....

         #
         # many things which need to be insider the controller
         #
       end
     end
   end

that 'private' methods __are__ allowed is really strange indeed.

regards.

-a
--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

i personally think instance_eval should be able to call both protected and
private methods...

it's just too hard to decide once and for all what should be private in an api
- this gives uses a way out.

take now for instance though - it seems i'm stuck since i cannot call the
methods i need without altering the source of rails... ;-(

-a

···

On Tue, 6 Dec 2005, nobuyoshi nakada wrote:

Hi,

At Tue, 6 Dec 2005 16:04:39 +0900,
Ara.T.Howard wrote in [ruby-talk:169057]:

   c.instance_eval{ p meth }

this throws an error, of course, but i'm too tired to remember how to work
around it.

Hmmm, it seems to have changed unintentionally, together with
rb_funcall2(), at Dec 1. Should I fix it?

Index: eval.c

RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.616.2.135
diff -U2 -p -u -r1.616.2.135 eval.c
--- eval.c 30 Nov 2005 15:51:05 -0000 1.616.2.135
+++ eval.c 6 Dec 2005 08:46:32 -0000
@@ -5901,11 +5901,11 @@ rb_call(klass, recv, mid, argc, argv, sc
    }

- if (mid != missing && scope == 0) {
+ if (mid != missing) {
  /* receiver specified form for private method */
- if (noex & NOEX_PRIVATE)
+ if ((noex & NOEX_PRIVATE) && && scope == 0)
      return method_missing(recv, mid, argc, argv, CSTAT_PRIV);

  /* self must be kind of a specified form for protected method */
- if (noex & NOEX_PROTECTED) {
+ if ((noex & NOEX_PROTECTED) && scope < 3) {
      VALUE defined_class = klass;

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

You could delegate:

         delegate(@controller).instance_eval do ... end

In the delegate object, make sure everything is public and that it uses #send to delegate. The cost is bouncing messages around a bit more and not having access to instance vars....

···

ara.t.howard@noaa.gov wrote:

    def encode msg
      @controller.instance_eval do
        #
        # many things which need to be insider the controller
        #
      end
    end

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

I actually really like Ruby's notion of private - just that you can't call the method with a receiver. When I first started with IRB I'd often look for methods using Something.methods.sort . It took me ages to realise why I was missing so many very common ones - because they're 'private' so that they can only be called on self.

I think it's really flexible :slight_smile:

···

On Tue, 06 Dec 2005 07:33:10 -0000, <ara.t.howard@noaa.gov> wrote:

On Tue, 6 Dec 2005, Joel VanderWerf wrote:

These are probably not helpful:

irb(main):012:0> c.instance_eval{ p send(:meth) }
42
=> nil
irb(main):013:0> c.instance_eval " p meth "
42
=> nil

The strange thing is that s/protected/private/ avoids the error:

irb(main):014:0> class C
irb(main):015:1> private
irb(main):016:1> def m2; 43; end
irb(main):017:1> end
=> nil
irb(main):018:0> c.instance_eval{ p m2 }
43

(ruby-1.8.2, anyway)

The original error (in the protected case) seem uncalled for....

[.. snip ..]

that 'private' methods __are__ allowed is really strange indeed.

--
Ross Bamford - rosco@roscopeco.remove.co.uk
"\e[1;31mL"

yeah - it's quite strange. unfortunately the 'send' approach won't work
because the actual usage is something like

Anyway, i think the 'send' of private methods is / will be changed in
1.9 so you can't do it anymore. Don't know about the other access
control runaround, where you can subclass a class with private meths
and declare them public (p 393 of pickax), if that will/is changed in
1.9

I agree.

James Edward Gray II

···

On Dec 6, 2005, at 10:25 AM, ara.t.howard@noaa.gov wrote:

i personally think instance_eval should be able to call both protected and
private methods...

Well, one thing you can do for now is not worry about altering the
rails sources, but just reopen the class in a personal library to
unprotect the needed method. Right?

Jacob Fugal

···

On 12/6/05, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

>> c.instance_eval{ p meth }

i personally think instance_eval should be able to call both protected and
private methods...

it's just too hard to decide once and for all what should be private in an api
- this gives uses a way out.

take now for instance though - it seems i'm stuck since i cannot call the
methods i need without altering the source of rails... ;-(

<possible stupid question>

Isn't access control kind of advisory anyway? Hopefully this isn't about to change???

irb(main):001:0> class Clz
irb(main):002:1> def amethod
irb(main):003:2> "amethod"
irb(main):004:2> end
irb(main):005:1> private :amethod
irb(main):006:1> end
=> Clz

irb(main):007:0> Clz.new.amethod
NoMethodError: private method `amethod' called for #<Clz:0xb7eddc18>
         from (irb):7

irb(main):008:0> class Clz
irb(main):009:1> public :amethod
irb(main):010:1> end
=> Clz

irb(main):011:0> Clz.new.amethod
=> "amethod"

</possible stupid question>

Or have I missed something ?

···

On Tue, 06 Dec 2005 15:01:48 -0000, Gene Tani <gene.tani@gmail.com> wrote:

yeah - it's quite strange. unfortunately the 'send' approach won't work
because the actual usage is something like

Anyway, i think the 'send' of private methods is / will be changed in
1.9 so you can't do it anymore. Don't know about the other access
control runaround, where you can subclass a class with private meths
and declare them public (p 393 of pickax), if that will/is changed in
1.9

--
Ross Bamford - rosco@roscopeco.remove.co.uk
"\e[1;31mL"

doesn't look like it....

harp:~ > ruby -e' p RUBY_VERSION; Class::new{ private; def meth() p 42 end }::new.instance_eval{ meth } '
"1.9.0"
42

-a

···

On Wed, 7 Dec 2005, Gene Tani wrote:

yeah - it's quite strange. unfortunately the 'send' approach won't work
because the actual usage is something like

Anyway, i think the 'send' of private methods is / will be changed in 1.9 so
you can't do it anymore. Don't know about the other access control
runaround, where you can subclass a class with private meths and declare
them public (p 393 of pickax), if that will/is changed in 1.9

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

try your example with 'protected'.

-a

···

On Wed, 7 Dec 2005, Ross Bamford wrote:

Or have I missed something ?

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

Or have I missed something ?

try your example with 'protected'.

-a

irb(main):025:0> class ClzThree
irb(main):026:1> protected
irb(main):027:1> def amethod
irb(main):028:2> "amethod"
irb(main):029:2> end
irb(main):030:1> end
=> nil

irb(main):031:0> ClzThree.new.amethod
NoMethodError: protected method `amethod' called for #<ClzThree:0xb7f48018>
         from (irb):31

irb(main):032:0> class ClzThree
irb(main):033:1> public :amethod
irb(main):034:1> end
=> ClzThree

irb(main):037:0> ClzThree.new.amethod
=> "amethod"

?

···

On Tue, 06 Dec 2005 16:21:12 -0000, <ara.t.howard@noaa.gov> wrote:

On Wed, 7 Dec 2005, Ross Bamford wrote:

         from :0

--
Ross Bamford - rosco@roscopeco.remove.co.uk
"\e[1;31mL"

yeah... technically that works. what i'm doing is having handlered register
with a controller to process requests based on mime_type. the handler really
needs to be run in the context of the controller to access all the good stuff
there but which 'good stuff' is not know a priori so i can't really use this
approach. also, it's probably bad mojo to start making methods public that
should be private on an object that's directly exposed to the web :wink:

cheers.

-a

···

On Wed, 7 Dec 2005, Ross Bamford wrote:

irb(main):025:0> class ClzThree
irb(main):026:1> protected
irb(main):027:1> def amethod
irb(main):028:2> "amethod"
irb(main):029:2> end
irb(main):030:1> end
=> nil

irb(main):031:0> ClzThree.new.amethod
NoMethodError: protected method `amethod' called for #<ClzThree:0xb7f48018>
       from (irb):31
       from :0

irb(main):032:0> class ClzThree
irb(main):033:1> public :amethod
irb(main):034:1> end
=> ClzThree

irb(main):037:0> ClzThree.new.amethod
=> "amethod"

?

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

Good points, especially the last one. Since all public methods of a
controller are exposed as actions that can be invoked (assuming a
route exists) from outside, you probably don't want them public. :slight_smile:
And upgrading the protection from protected to private (since your
code would work with private methods) could possibly cause problems
with other code that should have access but wouldn't. I guess you're
stuck for now.

:frowning:

Jacob Fugal

···

On 12/6/05, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

yeah... technically that works. what i'm doing is having handlered register
with a controller to process requests based on mime_type. the handler really
needs to be run in the context of the controller to access all the good stuff
there but which 'good stuff' is not know a priori so i can't really use this
approach. also, it's probably bad mojo to start making methods public that
should be private on an object that's directly exposed to the web :wink:

Phew - I was worried I'd missed a huge part of that section for a moment :slight_smile:

I understand that it's probably not the solution you wanted. It quite worries me sometimes that it's doable at all, but then I remember my arguments in the past with Java, about the difference between protecting for robust design and protecting for protection's sake.

(Of course this time it's probably a case of the former :slight_smile: I think it's good that it's your decision with Ruby though...)

···

On Tue, 06 Dec 2005 16:47:45 -0000, <ara.t.howard@noaa.gov> wrote:

On Wed, 7 Dec 2005, Ross Bamford wrote:

irb(main):025:0> class ClzThree
irb(main):026:1> protected
irb(main):027:1> def amethod
irb(main):028:2> "amethod"
irb(main):029:2> end
irb(main):030:1> end
=> nil

irb(main):031:0> ClzThree.new.amethod
NoMethodError: protected method `amethod' called for #<ClzThree:0xb7f48018>
       from (irb):31
       from :0

irb(main):032:0> class ClzThree
irb(main):033:1> public :amethod
irb(main):034:1> end
=> ClzThree

irb(main):037:0> ClzThree.new.amethod
=> "amethod"

?

yeah... technically that works. what i'm doing is having handlered register
with a controller to process requests based on mime_type. the handler really
needs to be run in the context of the controller to access all the good stuff
there but which 'good stuff' is not know a priori so i can't really use this
approach. also, it's probably bad mojo to start making methods public that
should be private on an object that's directly exposed to the web :wink:

cheers.

-a

--
Ross Bamford - rosco@roscopeco.remove.co.uk
"\e[1;31mL"