Ruby Code not in Any Method
Methods like attr_accessor
and has_many
are often called "mimic methods" because they kinda look like ruby keywords (mimic them) but they're in fact, as you and others have correctly pointed out, method calls.
dd = DooDad.new
dd.foo
When you're inside of a class definition the implicit receiver of all method calls and "variable definitions" isoutputs nil, and never spits out any
puts
stuffHow exactly does all that work?
self
, which in your case is DooDad
. So when you're writing
class DooDad
@foo = 1
end
you're actually defining an instance variable on self
, that happens to be the class itself , since you're inside of that classes definition. (and outside of any other class, module or method definitions)The method attr_accessor
on the other hand generates, with some help of metaprogramming, accessor methods for an instance variable of the objects that are instantiated from class DooDad
.
Back to your example:
class DooDad
attr_accessor :foo
puts "I happened!"
@foo = 7
end
With the stuff mentioned above, you should now understand that you're dealing with two different @foo variables, one for instances of class DooDad (i.e DooDad.new
), the other (the one you created by writing @foo = 7
) for the class DooDad itself!When calling the new
method on a class, you create an instance of it.
dd = DooDad.new
#=> dd is now an object of class DooDad
dd.foo
#=> You just called the "getter" method for an instance variable foo of object dd, which was never defined before, that's why it's returning nil.
The puts "I happened!"
statement, just as the other two in fact, gets evaluated as soon as the class is loaded, but not when you call new
on it. If you want the behaviour you described (doing stuff when calling
new
), I suggest implementing an initialize()
method for DooDad
, which will get called when you call new
:class DooDad
attr_accessor :foo
def initialize()
puts "I happened!"
@foo = 7
end
end
dd = DooDad.new
#=> outputs "I happened!" and sets dd.foo = 7
dd.foo
#=> 7
But why does @foo = 7
now set the instance variable of dd
and not DooDad
?When you define a method with the keyword
def
, you enter a new scope (you pass a scope gate). self
is now no longer the class, but instead an instance of that class, that you created with new
, just like dd
. So when you're writing @foo = 7
inside of a method definition, you're talking about variables for an instance of class DooDad
, not the class itself.This post is probably way too long and might not even satisfy as an answer, but I hope it was somewhat comprehensive.
Ruby code not executed after method call
@agent.get(url)
will fail with a bad url or network outage.
The problem in your code could be written as follows:
def do_something
begin
raise
puts "I will never get here!"
rescue
end
end
Since you can't get rid of the raise
, you need to do something inside the rescue
(most likely log it):begin
@agent.get(url)
# ...
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
Net::ProtocolError => e
log(e.message, e.callback)
end
Why can some classes and/or methods be called without instances of their parent class?
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object
class and hence seem to be globally available. Why? From any context Object
is always in the class hierarchy of self
and hence private methods on Object
are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class
class and may have singleton methods.class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods areclass A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name)
as followsstr = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on
Enumerable
) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again. Is there any way to call all the methods inside the class with the single line code in Ruby?
is it possible to call all the methods
by a single line code
Yes, that is possible.Personally, I don't get the obsession with squeezing everything into a single line. It does not make code smaller, it does not make code better, it does not make code easier to read. But it is technically possible.
In Ruby, line breaks are always optional. They can always be replaced with something else. If the line break is used as an expression separator, it can be replaced with a semicolon (;
), which is also an expression separator. If the line break is used to terminate some syntactic element, it can be replaced with either a semicolon (;
), a keyword (for example then
in if
and unless
, when
in case
, do
in for
, while
, and until
, and so on), and sometimes just whitespace.
So, you could write your code in a single line like this:
object = Sample.new(par1, par2); object.method1; object.method2; object.method3; object.method4; # … etc …
calling theWhether you write the code on one line or multiple lines has no effect on the space or time requirements of your program.methods
one by one using theobject.method_name(parameter)
is really hard and taking very long space and time.
If you execute the methods sequentially, the space requirement will be the maximum of the space requirements of all the methods and the time requirement will be the sum of the time requirements of all the methods.
You can execute the methods in parallel. In that case, the space requirement will be the sum of the space requirements of all the methods and the time requirement will be the maximum of the time requirements of all the methods plus any time needed to coordinate the parallel execution and merge the results back together. Also, executing the methods in parallel will change the result of the program!
Either way, you can only improve either space or time, not both.
Related Topics
How to Use Rspec to Test That a Model Using Paperclip Is Validating The Size of an Uploaded File
Case Insensitive Search in Rails
Save PDF File Shown by Pdfkit Middleware
Rails - Understanding Application.Js and Application.CSS
Shellwords.Shellescape Implementation for Ruby 1.8
How to Click on Specific Element in Canvas by Its Coordinates (Using Webdriver)
Ruby Dynamic Arguments in Dynamically Created Methods
Ruby on Rails Query with Sum and Group
Docker-Compose Restart Connection Pool Full
How to Deploy a Test App on Dreamhost Rails 3.0.4
Openssl::Ssl::Sslerror Ubuntu 12.04 Only
How to Host Gem in Github and Use It
How to Make Two Thor Tasks Share Options
How to Fix a Deadlock in Join() in Ruby
How Does The "#Map(&Proc)" Idiom Work When Introspecting Module Classes