Having a class method called only one time?

I’d like having a class method called only one time ?
Is it possible ?

suppose i do have a class “HFSFile” and i need to know the host ip.

i don’t want to call the method giving host ip each time i need it but
only the first time even i do instantiate several HFSFile, mostly
because it’s time consuming :

@h[:host_ip] = curl -s http://whatismyip.org.chomp

it is even in a while loop because sometimes curl returns ‘’.

Une Bévue [email protected] wrote:

I’d like having a class method called only one time ?
Is it possible ?

in the mean time i remembered java where we can do something like :

Array HOST_IP = [] # the array let me make the constant “mutable”

and where i need host_ip something like :

HOST_IP << get_host_ip if HOST_IP.empty?

where get_host_ip is a call to :
curl -s http://whatismyip.org.chomp

a more clever way ?

also i want to avoid calling curl if i don’t nee host ip…

You can “memoize” the result of such an operation in an instance
variable by
doing

@cached_result ||= big_expensive_operation

This will use the value of @cached_result unless it’s unset/nil,
otherwise
it will invoke the expensive operation and store the result in an ivar

2010/6/2 Une Bévue [email protected]

2010/6/2 Une Bévue [email protected]:

end

I think it looks cleaner using the idiom Tony described:

class HFSFile
def host_ip
@host_ip ||= host_ip_get
end
private

def host_ip_get
$stderr.puts “‘host_ip_get’ was called!” # called 1 time for 2
instantiations.
host_ip = ‘’
while host_ip.empty?
host_ip = curl -s http://whatismyip.org.chomp
end
host_ip
end
end

Jesus.

Tony A. [email protected] wrote:

You can “memoize” the result of such an operation in an instance variable by
doing

@cached_result ||= big_expensive_operation

This will use the value of @cached_result unless it’s unset/nil, otherwise
it will invoke the expensive operation and store the result in an ivar

fine thanks, that’s cleaner than my code !

Jesús Gabriel y Galán [email protected] wrote:

instantiations.
host_ip = ‘’
while host_ip.empty?
host_ip = curl -s http://whatismyip.org.chomp
end
host_ip
end
end

i do agree, it’s cleaner and much more rubyish, thanks !

Une Bévue [email protected] wrote:

Array HOST_IP = [] # the array let me make the constant “mutable”

it seems to work like that :

class HFSFile

HOST_IP = []

def host_ip
return HOST_IP.first unless HOST_IP.empty?
HOST_IP << host_ip_get
return @h[:host_ip]
end

private

def host_ip_get
$stderr.puts “‘host_ip_get’ was called!” # called 1 time for 2
instantiations.
@h[:host_ip] = ‘’
while @h[:host_ip].empty?
@h[:host_ip] = curl -s http://whatismyip.org.chomp
end
return @h[:host_ip]
end

end

2010/6/2 Une Bévue [email protected]

it is even in a while loop because sometimes curl returns ‘’.


« Les faiblesses des hommes font la force des femmes. »
(Voltaire)

This is basically the same as what other people have said, but uses
begin
… end to do the entire calculation in one method. Also, addresses that
it
should only calculate once, across all instances.

class HFSFile

assumes all instances of this class have the same host_ip

frozen just b/c a lot of objects are going to be using it

def self.host_ip
@@host_ip ||= begin
puts “calculating host_ip”
ip = curl -s http://whatismyip.org.chomp until ip && !ip.empty?
ip.freeze
end
end

instance forwards to class

if there is a better way to do this, someone let me know

def host_ip
self.class.host_ip
end

end

hfs1 = HFSFile.new
puts hfs1.host_ip
puts hfs1.host_ip

hfs2 = HFSFile.new
puts hfs2.host_ip
puts hfs2.host_ip


Also, the delightful Ruby Best Practices discusses lazy evaluation in
chapter 5. You can download a copy at http://rubybestpractices.com/ and
if
you feel you got something worthwhile, you might consider purchasing it
as
well :slight_smile:


And depending on where you are going with this, you could also consider
rake, which is built around tasks and dependencies, and won’t execute a
task
more than one time (per user invocation).

On 6/2/10, Josh C. [email protected] wrote:

instance forwards to class

if there is a better way to do this, someone let me know

def host_ip
self.class.host_ip
end

Module#module_function is probably the best/shortest way to share the
have the same method be both a class and instance method.

Josh C. [email protected] wrote:

This is basically the same as what other people have said, but uses begin
… end to do the entire calculation in one method. Also, addresses that it
should only calculate once, across all instances.

exactly what i wanted.


Also, the delightful Ruby Best Practices discusses lazy evaluation in
chapter 5. You can download a copy at http://rubybestpractices.com/ and if
you feel you got something worthwhile, you might consider purchasing it as
well :slight_smile:

for sure, after reading it quicly.


And depending on where you are going with this, you could also consider
rake, which is built around tasks and dependencies, and won’t execute a task
more than one time (per user invocation).

for the time being my needs are more toward some IDE.

On 6/2/10, Une Bévue [email protected] wrote:

Caleb C. [email protected] wrote:

Module#module_function is probably the best/shortest way to share the
have the same method be both a class and instance method.

my class extend File class i didn’t mention it :

class HFSFile < File

then i’d have to use mixin for your solution ?

I was really responding to Josh, regarding having a method be both an
instance and class method. It was not directly applicable to your
question.

Caleb C. [email protected] wrote:

Module#module_function is probably the best/shortest way to share the
have the same method be both a class and instance method.

my class extend File class i didn’t mention it :

class HFSFile < File

then i’d have to use mixin for your solution ?