Forum: Ruby getting around access control

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.
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 08:05
(Received via mailing list)
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
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 vjoel (Guest)
on 2005-12-06 08:29
(Received via mailing list)
Ara.T.Howard wrote:
>   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....
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 08:33
(Received via mailing list)
On Tue, 6 Dec 2005, Joel VanderWerf wrote:

>
> The original error (in the protected case) seem uncalled for....
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
         #
         # many things which need to be insider the controller
         #
       end
     end
   end

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

regards.

-a
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 vjoel (Guest)
on 2005-12-06 09:06
(Received via mailing list)
ara.t.howard@noaa.gov wrote:

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

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....
04a56914cc09f0858d3fca2bf4cbde34?d=identicon&s=25 nobuyoshi.nakada (Guest)
on 2005-12-06 09:50
(Received via mailing list)
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;
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 rosco (Guest)
on 2005-12-06 11:17
(Received via mailing list)
On Tue, 06 Dec 2005 07:33:10 -0000, <ara.t.howard@noaa.gov> wrote:

>>
>> (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.
>

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 :)
9dfe8c734b0f9b37a4e218425c0a2138?d=identicon&s=25 gene.tani (Guest)
on 2005-12-06 16:07
(Received via mailing list)
> 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
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 rosco (Guest)
on 2005-12-06 16:48
(Received via mailing list)
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
>

<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 ?
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 17:24
(Received via mailing list)
On Wed, 7 Dec 2005, Ross Bamford wrote:

> Or have I missed something ?

try your example with 'protected'.


-a
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 17:29
(Received via mailing list)
On Tue, 6 Dec 2005, nobuyoshi nakada wrote:

> rb_funcall2(), at Dec 1.  Should I fix it?
>     }
> +	if ((noex & NOEX_PROTECTED) && scope < 3) {
> 	    VALUE defined_class = klass;


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
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2005-12-06 17:33
(Received via mailing list)
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...

I agree.

James Edward Gray II
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 17:37
(Received via mailing list)
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

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
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 lukfugl (Guest)
on 2005-12-06 17:37
(Received via mailing list)
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... ;-(

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
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 rosco (Guest)
on 2005-12-06 17:41
(Received via mailing list)
On Tue, 06 Dec 2005 16:21:12 -0000, <ara.t.howard@noaa.gov> wrote:

> On Wed, 7 Dec 2005, Ross Bamford wrote:
>
>> 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
         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"

?
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 ara.t.howard (Guest)
on 2005-12-06 17:49
(Received via mailing list)
On Wed, 7 Dec 2005, Ross Bamford wrote:

>        from (irb):31
> ?
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 ;-)

cheers.

-a
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 lukfugl (Guest)
on 2005-12-06 17:57
(Received via mailing list)
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 ;-)

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. :)
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.

:(

Jacob Fugal
82e62c756d89bc6fa0a0a2d7f2b1e617?d=identicon&s=25 rosco (Guest)
on 2005-12-06 18:14
(Received via mailing list)
On Tue, 06 Dec 2005 16:47:45 -0000, <ara.t.howard@noaa.gov> wrote:

>> irb(main):031:0> ClzThree.new.amethod
>> irb(main):037:0> ClzThree.new.amethod
> 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 ;-)
>
> cheers.
>
> -a

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

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 :) I think it's
good that it's your decision with Ruby though...)
This topic is locked and can not be replied to.