Don't the Ruby methods instance_eval() and send() negate the benefits of private visibility?
If you really want to protect instances of Widget
, you can do this (and a bunch of other stuff; the code here is not a complete security solution, merely indicative):
class Widget
def some_public_method
...
end
private
def utility_method
...
end
def send(method, *args, &block)
raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
end
def instance_eval(&block)
raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
end
class <<self
private
def class_eval(&block)
raise NotImplementedError.new('Widget is secure. Stop trying to hack me.')
end
end
end
Widget.freeze
Why can I access private/protected methods using Object#send in Ruby?
Technically: Because send
doesn't do anything to check method visibility. (It would be more work to do so.)
Philosophically: Ruby is a very permissive language. You can already just open up a class and make any method you want public. The language designers implemented send
in a way that allows it to override the restrictions normally imposed by private
. Ruby 1.9 was originally going to have two variants, a private
-respecting send
and an unsafe variant called send!
, but this was apparently dropped for backwards compatibility.
As for what private
, protected
and public
mean:
public
methods can be called by any senderprotected
methods cannot be called outside of an instance of the method's class or an instance of a subclassprivate
methods cannot be called with an explicit receiver (with a couple of exceptions, such as setter methods, which always have to have an explicit receiver, and so can be called within the class that way)
Is this a simple way to violate the encapsulation in ruby?
What do you expect from a language that lets you write
String = Array
puts String.new.inspect
#=> []
or
class Fixnum
def +(b)
self-b
end
end
puts 1+2
#=> -1
?
On a more serious note, almost nothing is forbidden in Ruby : it makes it easier to experiment and to learn Ruby inner workings. In some cases, it makes it possible to write more concise code or get "magical" behaviors that would be harder or impossible to reproduce with a stricter language.
In your example, it's possible to call a private method, but you cannot use the usual syntax.
Where is the methods and operators defined that allow to do class self; def foo; end; end inside class definition?
This syntax is used in ruby to access an object's metaclass, or singleton class. The metaclass is used to store methods for an individual object.
obj = # whatever...
class <<obj
# here, self is defined as obj's metaclass
# so foo will be an instance method of obj's metaclass
# meaning that we can call obj.foo
def foo
# ...
end
end
# this is equivalent to the above
def obj.foo
# ...
end
This is a core part of the language, and isn't defined in any library.
Preferred Ruby-ist way of declaring access controls
The only place I've ever seen the second method used is in Ruby books, and only as a "You can also do this" example.
And you very rarely see the use of "public" like in the first method, as it's the default and people just define all their public methods before any protected/private declarations.
Related Topics
Rails in Rendering Unnecessary Information
How to Find the Average of 3 Date in Ruby on Rails or Ruby
How to Write the JSON Schema If JSON Has Multiple Data Set
Login Session Data Not Persisting in Rails 6
How to Keep Sending Emails to Users Every Week Depending on User Date Input in Rails
Ruby Ternary Operator and Method Call
How to Collect Real-Time Tweets
How to Implement Injection in Ruby
What's the Differences Between Ruby on Rails and Ruby
How to Replace a Pattern in Ruby Array
Sum of Arrays of Different Size
What Ruby and Rails Developers Ought to Know
Continuous Integration for Ruby on Rails
Determining Type of an Object in Ruby