I want a method to be executed every 5 minutes, I implemented whenever for ruby (cron). But it does not work. I think my method is not accessible.
The method I want to execute is located in a class. I think I have to make that method static so I can access it with MyClass.MyMethod. But I can not find the right syntax or maybe I am looking in the wrong place.
Schedule.rb
every 5.minutes do
runner "Ping.checkPings"
end
Ping.rb
def checkPings
gate = Net::Ping::External.new("10.10.1.1")
#monitor_ping = Ping.new()
if gate.ping?
MonitorPing.WAN = true
else
MonitorPing.WAN = false
end
#monitor_ping.save
end
To declare a static method, write ...
def self.checkPings
# A static method
end
... or ...
class Myclass extend self
def checkPings
# Its static method
end
end
You can use static methods in Ruby like this:
class MyModel
def self.do_something
puts "this is a static method"
end
end
MyModel.do_something # => "this is a static method"
MyModel::do_something # => "this is a static method"
Also notice that you're using a wrong naming convention for your method. It should be check_pings instead, but this does not affect if your code works or not, it's just the ruby-style.
Change your code from
class MyModel
def checkPings
end
end
to
class MyModel
def self.checkPings
end
end
Note there is self added to the method name.
def checkPings is an instance method for the class MyModel whereas def self.checkPings is a class method.
Instead of extending self for the whole class, you can create a block that extends from self and define your static methods inside.
you would do something like this :
class << self
#define static methods here
end
So in your example, you would do something like this :
class Ping
class << self
def checkPings
#do you ping code here
# checkPings is a static method
end
end
end
and you can call it as follows : Ping.checkPings
There are some ways to declare a static method in RoR.
#1
class YourClassName
class << self
def your_static_method (params)
# Your code here
end
end
end
#2
class YourClassName
def self.your_status_method
// Your code here
end
end
You cannot have static methods in Ruby. In Ruby, all methods are dynamic. There is only one kind of method in Ruby: dynamic instance methods.
Really, the term static method is a misnomer anyway. A static method is a method which is not associated with any object and which is not dispatched dynamically (hence "static"), but those two are pretty much the definition of what it means to be a "method". We already have a perfectly good name for this construct: a procedure.
Related
I want a piece of code to run before any other static methods run, is it possible to do something in the spirit of the following?
class MyClass
def self.initialize
#stuff = 1
end
def self.print_stuff
puts #stuff
end
end
My Ruby version of interest is 2.3.
Every chunk of code in Ruby is an expression. Even a class definition is a series of expressions: method definitions are expressions that have the side-effect of adding the method to the class.
This is how meta-programming methods work. attr_reader is a private method call where the implicit self is the class. So, long story short, you aren't restricted inside a class body, you can put whatever code you want to run in the context of the class:
class MyClass
#stuff = 1
def self.print_stuff
puts #stuff
end
end
There's no such thing as an explicit metaclass initializer. The class itself is "initialized" as it's defined, so it's perfectly valid to do this:
class MyClass
# Code here will be executed as the class itself is defined.
#stuff = 1
def self.print_stuff
puts #stuff
end
end
MyClass.print_stuff
Remember that def itself is a form of method call and defining a class in Ruby involves sending a bunch of messages (method calls) around to the proper context objects, such as the class itself as it's being defined.
I was wondering how I could call a method in an instance of a class in another class.
This is what I came up with
class ClassA
def method
return "This is a method_from_class_A"
end
end
class ClassB
def initialize
#method_from_class_A=instance.method
end
def method_calls_method
#method_from_class_A
end
end
instance=ClassA.new
instance2=ClassB.new
puts instance2.method_calls_method
But I get this error:
Testing.rb:9:in initialize': undefined local variable or method
instance' for # (NameError) from
Testing.rb:19:in new' from Testing.rb:19:in'
How could I fix it?
Thank you for your response.
From your description this seems to be what you're going for:
class ClassB
def initialize
#instance_of_class_a = ClassA.new
end
def method_calls_method
#instance_of_class_a.method
end
end
Or to pass in the ClassA instance (this is called dependency injection):
class ClassB
def initialize(class_a_instance)
#instance_of_class_a = class_a_instance
end
def method_calls_method
#instance_of_class_a.method
end
end
instance_a = ClassA.new
instance_b = ClassB.new(instance_a)
puts instance_b.method_calls_method
Another Option would be to take a look at class methods: https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/45-more-classes/lessons/113-class-variables
So in your code it would look similar to this:
class ClassA
def self.method
return "This is a method_from_class_A"
end
end
class ClassB
def method_calls_method
ClassA.method
end
end
instance=ClassB.new
puts instance.method_calls_method
*Notice the self. in ClassA to signify a class method. This is similar to a static method in other languages.
According to wikipedia: https://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods
Class(static) methods are meant to be relevant to all the instances of a class rather than to any specific instance.
You see class methods used a lot in the ruby Math class:
http://ruby-doc.org/core-2.2.2/Math.html
For example taking a square root of a number in is done by using the class method Math.sqrt. This is different from an instance method which would look like object.method instead Class.method. There are a lot of resources and tutorials out that explains this concept in more detail and probably clearer.
In Java, I am used to writing an abstract class that does some setup work and then delegates to the concrete class like this:
public abstract class Base {
public void process() {
// do some setup
//...
// then call the concrete class
doRealProcessing();
}
protected abstract void doRealProcessing();
}
public class Child extends Base {
#Override
protected void doRealProcessing() {
// do the real processing
}
}
I am having a hard time doing this in Ruby because I don't have abstract classes or methods. I also read that "you aren't supposed to need abstract classes or methods in Ruby and that I should stop trying to write Java in Ruby".
I would love to know what is the right way to implement the equivalence in Ruby?
Welcome to dynamically typed languages! You were probably nervous about just defining some function that wasn't declared anywhere. Don't be worried. It is very easy:
class Base
def process
# ...
real_processing
end
def real_processing # This method is optional!
raise "real_processing not implemented in #{self.class.name}"
end
end
class Child < Base
def real_processing
# ...
end
end
b = Child.new
b.process
EDIT: Here's another option for you which avoids the need to have two different method names:
class Base
def process
# ...
end
end
class Child < Base
def process
# ...
super # calls the process method defined above in Base
# ...
end
end
Here's how you can do the template pattern in Ruby:
class Template
def template_method
perform_step1
perform_step2
#do some extra work
end
def perform_step1
raise "must be implemented by a class"
end
def perform_step2
raise "must be implemented by a class"
end
end
class Implementation < Template
def perform_step1
#implementation goes here
end
def perform_step2
#implementation goes here
end
end
http://andymaleh.blogspot.com/2008/04/template-method-design-pattern-in-ruby.html
You don't see much of this in Ruby for this use case, because the pattern
do some household setup ( make a connection to a resource for
instance)
do something real with it
teardown household job (f.i. close connection)
is baked into ordinary methods:
# pseudocode:
def a_method(an_argument)
# do some setup with an_argument
yield(a_result)
# do some teardown
end
# use like:
a_method(the_argument){|the_result| puts "real processing with #{the_result}"}
Is initialize method (constructor) private or public in ruby?
Let's see:
class Test
def initialize; end
end
p Test.new.private_methods.sort.include?(:initialize)
This prints true, so initialize is a private method. This makes sense, it is only called by the new class method if the object is created. If we want, we can do something like this:
class Test
def initialize
#counter = 0
end
def reset!
initialize
end
end
Misusing the constructor like this could however lead to problems if it does more than simple variable initialization.
The initialize method in a class automatically becomes Private.
You can check it using:
puts ClassName.private_methods.sort
I must be missing something about how people do this in Ruby.
If '#protected' is uncommented we get:
in 'what': protected method 'zoop' called for Foo:Class (NoMethodError)
Is there a better way to approach protected class methods?
class Foo
class << self
#protected
def zoop
"zoop"
end
end
public
def what
"it is '#{self.class.zoop}'"
end
protected
end
a = Foo.new
p a.what # => "it is 'zoop'"
I would like zoop to be protected or private (no calling 'Foo.zoop'), but so far, I can't seem to find an elegant way.
It barely matters to make methods private or protected in Ruby, since you can just call send() to get around them.
If you want zoop to stay protected, use send() like this:
def what
"it is '#{self.class.send(:zoop)}'"
end
Upon further discussions with rue: and drbrain: in ruby-lang, it turns out that my impulse to save memory by placing utility functions at the class level was misplaced.
In Ruby, the instance methods hang off the class anyway, and the answer is to go ahead and place the utility functions at the instance level as private.
In summary, a utility function that is accessed only by instance methods:
class Foo
def what
"it is '#{zoop}'"
end
private
def zoop
"zoop"
end
end
p Foo.new.what # => "it is 'zoop'"
For a utility function that needs to be called from instance and class methods, a nested module seemed to be a popular approach:
class Foo
module Util
def self.zoop
"zoop"
end
end
def what
"it is '#{Util.zoop}'"
end
class << self
def class_what
"for all time it is '#{Util.zoop}'"
end
end
end
p Foo.new.what # => "it is 'zoop'"
p Foo.class_what # => "for all time it is 'zoop'"
p Foo::Util.zoop # visible, alas