having a class method called only one time ?

U

Une Bévue

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 ''.
 
U

Une Bévue

Une Bévue said:
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...
 
U

Une Bévue

Une Bévue said:
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
 
T

Tony Arcieri

You can "memoize" the result of such an operation in an instance variable b=
y
doing

@cached_result ||=3D 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=E9vue said:
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] =3D `curl -s http://whatismyip.org`.chomp

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


--=20
Tony Arcieri
Medioh! A Kudelski Brand
 
J

Jesús Gabriel y Galán

2010/6/2 Une B=E9vue said:
Une B=E9vue said:
Array HOST_IP =3D [] # the array let me make the constant "mutable"

it seems to work like that :

class HFSFile

=A0HOST_IP =3D []

=A0...

=A0def host_ip
=A0 =A0return HOST_IP.first unless HOST_IP.empty?
=A0 =A0HOST_IP << host_ip_get
=A0 =A0return @h[:host_ip]
=A0end

=A0...

=A0private

=A0def host_ip_get
=A0 =A0$stderr.puts "'host_ip_get' was called!" # called 1 time for 2
instantiations.
=A0 =A0@h[:host_ip] =3D ''
=A0 =A0while @h[:host_ip].empty?
=A0 =A0 =A0@h[:host_ip] =3D `curl -s http://whatismyip.org`.chomp
=A0 =A0end
=A0 =A0return @h[:host_ip]
=A0end

=A0...

end
--

I think it looks cleaner using the idiom Tony described:

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

def host_ip_get
$stderr.puts "'host_ip_get' was called!" # called 1 time for 2
instantiations.
host_ip =3D ''
while host_ip.empty?
host_ip =3D `curl -s http://whatismyip.org`.chomp
end
host_ip
end
end

Jesus.
 
U

Une Bévue

Jesús Gabriel y Galán said:
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

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

Une Bévue

Tony Arcieri said:
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 !
 
J

Josh Cheek

2010/6/2 Une B=E9vue said:
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] =3D `curl -s http://whatismyip.org`.chomp

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

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 ||=3D begin
puts "calculating host_ip"
ip =3D `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 =3D HFSFile.new
puts hfs1.host_ip
puts hfs1.host_ip

hfs2 =3D 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 :)

-----

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 tas=
k
more than one time (per user invocation).
 
C

Caleb Clausen

# 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.
 
U

Une Bévue

Caleb Clausen said:
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 ?
 
U

Une Bévue

Josh Cheek said:
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 :)


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

Caleb Clausen

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,154
Messages
2,570,870
Members
47,400
Latest member
FloridaFvt

Latest Threads

Top