To make dot method dot method work?

here is the class
class Mycompute
def initialize(str)
@str=str
end
def values
@@result=@str
end
def up
@@result.upcase
end
end
irb(main):012:0> Mycompute.new(“Abc”).values
=> “Abc”
irb(main):013:0>
irb(main):014:0* Mycompute.new(“Abc”).up
=> “ABC”
irb(main):015:0> Mycompute.new(“Abc”).values.up
NoMethodError: undefined method `up’ for “Abc”:String
from (irb):15
from :0

would you tell me how to fix it to make
Mycompute.new(“Abc”).values.up output “ABC”?

On 09/23/2010 05:17 AM, Pen T. wrote:

end

would you tell me how to fix it to make
Mycompute.new(“Abc”).values.up output “ABC”?
The most obvious way I see to do it is to use an object attribute
instead of a class attribute. in other words, @result instead of
@@result. Is there a reason why you want to use a class attribute in
this instance? A class attribute is not an attribute of the object.

i’m totally newbie in ruby, sorry if im talking about smth obvious, just
trying to help, but do u know u code doesn’t work if it’s like this ?

class Mycompute
def initialize(str)
@str=str
end
def values
@@result=@str
end
def up
@@result.upcase
end
end

puts Mycompute.new(“Abc”).up

but it do if u do this:

class Mycompute
def initialize(str)
@str=str
@@result=str
end

puts Mycompute.new(“Abc”).up #will work.

irb(main):012:0> Mycompute.new(“Abc”).values
=> “Abc”
irb(main):013:0>
irb(main):014:0* Mycompute.new(“Abc”).up
=> “ABC”
irb(main):015:0> Mycompute.new(“Abc”).values.up
NoMethodError: undefined method `up’ for “Abc”:String
from (irb):15
from :0

Let’s follow what happens, and maybe I will make more sense.
Mycompute.new(“Abc”)
^^^^^^^^^^^^^^^^^^^^
creates a new object of class Mycompute with an instance variable of
@str equalling the string “Abc”

Mycompute.new(“Abc”).values
^^^^^^^^^^^^^
Creates another new object with instance variable equal to “Abc” and
assigns value of @str to Class attribute @@result through the ‘values’
method.
Mycompute.new(“Abc”).values returns a string

Mycompute.new(“Abc”).values.up
^^^
Now we must think about the type of what is returned from our
chained
methods.

  1. Mycompute.new creates a new object of type Mycompute, Mycompute
    objects have a method called ‘values’
  2. the method ‘values’ returns a string, and you attempt to call a
    method defined for class Mycompute on an object of type String.

that don’t work.

On Sep 23, 2010, at 7:30 AM, G Brandon H. wrote:

@@result.upcase

from :0

would you tell me how to fix it to make
Mycompute.new(“Abc”).values.up output “ABC”?
The most obvious way I see to do it is to use an object attribute
instead of a class attribute. in other words, @result instead of
@@result. Is there a reason why you want to use a class attribute in
this instance? A class attribute is not an attribute of the object.

You’ve defined #up on Mycompute instances, but not on string. If
Mycompute#values returned a Mycompute instance, then you could write
the expression that way. Since #values seems to want to be a plain
String, what about turning the expression around:

Mycompute.new(“Abc”).up.values

(and I do find it odd to use “values” rather than “value” since only
one thing is returned)

class Mycompute
def initialize(str)
@str = str
end
def up
self.class.new(@str.upcase)
end
def values
@str
end
def to_s
@str.dup
end
end

irb> Mycompute.new(“Abc”)
=> #<Mycompute:0x63cb8 @str=“Abc”>
irb> Mycompute.new(“Abc”).up
=> #<Mycompute:0x60d74 @str=“ABC”>
irb> Mycompute.new(“Abc”).values
=> “Abc”
irb> Mycompute.new(“Abc”).up.values
=> “ABC”

irb> puts Mycompute.new(“Abc”)
Abc
=> nil
irb> puts Mycompute.new(“Abc”).up
ABC
=> nil
irb> puts Mycompute.new(“Abc”).values
Abc
=> nil
irb> puts Mycompute.new(“Abc”).up.values
ABC
=> nil

Does that help you?

-Rob

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

thinks for everyone,i learned :
1.it’s not necessary to use @@ in the code
2.to use self to get an object
here is the code what i want
class Mycompute
def initialize(str)
@str=str
end
def values
@result=@str
self
end
def up
@[email protected]
end
end

Mycompute.new(“Abc”).values.up
=> “ABC”
there is another problem ,
Mycompute.new(“Abc”).values+“d”
NoMethodError: undefined method `+’ for #<Mycompute:0xb74ad8d4
@str=“Abc”, @result=“Abc”>
how to make Mycompute.new(“Abc”).values+“d” output “Abcd”?

When you call foo.bar.baz then you are:

  1. calling method ‘foo’
  2. that returns an object
  3. calling ‘bar’ on the object returned from (2)
  4. that returns an object
  5. calling ‘baz’ on the object returned from (4)

So:

class Mycompute
def initialize(str)
@str=str
end
def values
@@result=@str
end
def up
@@result.upcase
end
end
irb(main):012:0> Mycompute.new(“Abc”).values
=> “Abc”
irb(main):013:0>
irb(main):014:0* Mycompute.new(“Abc”).up
=> “ABC”

That returns a string (and sets @@result as a side-effect).

irb(main):015:0> Mycompute.new(“Abc”).values.up
NoMethodError: undefined method `up’ for “Abc”:String
from (irb):15
from :0

Strings don’t have a method called ‘up’ - but they do have ‘upcase’.

So you can do:

Mycompute.new(“Abc”).values.upcase

Or else perhaps this is what you want:

obj = Mycompute.new(“Abc”)
obj.values
obj.up

Or else:

def values
@@result = @str
self
end

in which case Mycompute.new(“Abc”).values.up will work, because your
values method returns the object itself, not a String.

please see
irb(main):018:0> [1,2,3]
=> [1, 2, 3]
irb(main):019:0> [1,2,3].size
=> 3
irb(main):020:0> [1,2,3].size.to_f
=> 3.0

how to fix my code to make it
Mycompute.new(“Abc”).values
=> “Abc”
Mycompute.new(“Abc”).values.up
=> “ABC”
if my code is code1
code1
class Mycompute
def initialize(str)
@str=str
end
def values
@result=@str
self
end
def up
@[email protected]
end
end
i can get :
Mycompute.new(“Abc”).values
=> #<Mycompute:0xb770995c @result=“Abc”, @str=“Abc”>
irb(main):034:0> Mycompute.new(“Abc”).values.up
=> “ABC”
if my code is code2
code2
class Mycompute
def initialize(str)
@str=str
end
def values
@result=@str
end
def up
@[email protected]
end
end
i can get
irb(main):046:0> Mycompute.new(“Abc”).values
=> “Abc”
irb(main):047:0> Mycompute.new(“Abc”).values.up
NoMethodError: undefined method `up’ for “Abc”:String
from (irb):47
from :0
how to write code to make both of them happen?
Mycompute.new(“Abc”).values
=>“Abc”
Mycompute.new(“Abc”).values.up
=> “ABC”

class String
def up
self.upcase
end
end

class Mycompute < String
def initialize(str)
@str=str
end
def value
@result=@str
end
def up
@[email protected]
end
end

puts Mycompute.new(“string”).value.up —> “STRING”

On Thu, Sep 23, 2010 at 6:22 PM, Pen T. [email protected] wrote:

here is the code what i want

Not totally :slight_smile:

class Mycompute
def initialize(str)
@str=str
end

def values
@result=@str
self
end

how to make Mycompute.new(“Abc”).values+“d” output “Abcd”?

def values
@str
end

You’re returning an object rather than a string, and that object has no
such method as “+” :slight_smile:

there is another way to solve it(an expert in stackover help me)
class Mycompute
def initialize(str)
@str=str
end
def values
@@result=@str
def @@result.up
self.upcase
end
@@result
end
def up
@@result.upcase
end
end

Mycompute.new(“Abc”).values #=> “Abc”
Mycompute.new(“Abc”).up #=> “ABC”
Mycompute.new(“Abc”).values.up #=> “ABC”

Pen T. wrote:

there is another way to solve it(an expert in stackover help me)
class Mycompute
def initialize(str)
@str=str
end
def values
@@result=@str
def @@result.up
self.upcase
end
@@result
end
def up
@@result.upcase
end
end

Do you understand what you’ve done? At runtime you’ve added a custom
method called ‘up’ to the String object you’ve returned. The String
object is now a String with an extra method. It’s a cool feature of
Ruby, but not one you would want to use widely as a beginner.

And why are you still assigning to @@result?

Perhaps it would be better if you showed some real code, what you’re
actually trying to do. This ‘Mycompute’ example is not particularly
useful, because right now it’s just a wrapper for a String.

  1. why are you still assigning to @@result?
    if i change code1 into code2
    code1
    class Mycompute
    def initialize(str)
    @str=str
    end
    def values
    @@result=@str
    def @@result.up
    self.upcase
    end
    @@result
    end
    def up
    @@result.upcase
    end
    end
    code2

class Mycompute
def initialize(str)
@str=str
end
def values
@result=@str
def @result.up
self.upcase
end
@result
end
def up
@result.upcase
end
end
code2 can only get :

Mycompute.new(“Abc”).values
=> “Abc”
irb(main):017:0> Mycompute.new(“Abc”).up
NoMethodError: undefined method upcase' for nil:NilClass from (irb):13:inup’
from (irb):17
from :0
irb(main):018:0> Mycompute.new(“Abc”).values.up
=> “ABC”
code1 can get
Mycompute.new(“Abc”).values #=> “Abc”
Mycompute.new(“Abc”).up #=> “ABC”
Mycompute.new(“Abc”).values.up #=> “ABC”

2.here is my real code
real code1
require ‘rubygems’
require ‘mysql’
require ‘date’
class Analyse
@@result=[]
def self.vol(symbol,cycle)
cycle=cycle.to_i
dbh = Mysql.real_connect(“localhost”, “root”, “*****")
dbh.query(“use stock;”)
result=dbh.query(“select symbol,date,open,high,low,close from
#{symbol} order by date asc;”)
compute=[]
result.each{|row| compute<<row.join(";")}
compute.each.with_index{|row,idx|
row=row.split(";")
if idx> cycle-2 then
if row[4].to_f==0 then
row[6]=“nil”
else
mymax=[]
mymin=[]
for i in idx-cycle+1…idx
mymax<<compute[i].split(";")[3].to_f
mymin<<compute[i].split(";")[4].to_f
end
max=mymax.max
min=mymin.min
row[6]=format("%.2f",100
(max-min)/min)
end
else
row[6]=“nil”
end
@@result<<row.join(”;")
}
end

def mean
amean=[]
@@result.each{|line|
line.each{|item|
amean<< item.chomp.split(";")[-1].to_f
}}
amean=amean.compact
format("%.2f",amean.inject(0){|s,n| s+n}/(amean.size.to_f)).to_f
end
end

1)vol method can get stock Volatility,every 5 day Volatility,such
as
Analyse.vol(“c”,“5”) can get
c;2010-09-09;3.89;3.95;3.88;3.91;4.19
c;2010-09-10;3.92;3.94;3.9;3.91;4.19
c;2010-09-13;3.96;4.01;3.96;3.99;4.97
c;2010-09-14;3.98;3.99;3.91;3.94;4.70
c;2010-09-15;3.92;3.93;3.9;3.92;3.35
c;2010-09-16;3.89;3.98;3.88;3.97;3.35
c;2010-09-17;4;4.02;3.95;3.95;3.61
c is the stock name ,the last column is volatility
2)i want to make Analyse.vol(“c”,“5”).mean run
real code1 can get :
NoMethodError: undefined method mean' for nil:NilClass that is to say ,in real code1 Analyse.vol("c","5") can get what i want Analyse.vol("c","5").mean can't if i change real code1 into real code2 such as: real code2 require 'rubygems' require 'mysql' require 'date' class Analyse @@result=[] def self.vol(symbol,cycle) object = Analyse.new cycle=cycle.to_i dbh = Mysql.real_connect("localhost", "root", "******") dbh.query("use stock;") result=dbh.query("select symbol,date,open,high,low,close from#{symbol}` order by date asc;")
compute=[]
result.each{|row| compute<<row.join(";")}
compute.each.with_index{|row,idx|
row=row.split(";")
if idx> cycle-2 then
if row[4].to_f==0 then
row[6]=“nil”
else
mymax=[]
mymin=[]
for i in idx-cycle+1…idx
mymax<<compute[i].split(";")[3].to_f
mymin<<compute[i].split(";")[4].to_f
end
max=mymax.max
min=mymin.min
row[6]=format("%.2f",100*(max-min)/min)
end
else
row[6]=“nil”
end
@@result<<row.join(";")
}
return object
end

def mean
amean=[]
@@result.each{|line|
line.each{|item|
amean<< item.chomp.split(";")[-1].to_f
}}
amean=amean.compact
format("%.2f",amean.inject(0){|s,n| s+n}/(amean.size.to_f)).to_f
end
end
real code2 can get:
Analyse.vol(“c”,“5”)
=> #Analyse:0xb774af24
Analyse.vol(“c”,“5”).mean
=> 7.62

what i want is real code3 which can get
1)Analyse.vol(“c”,“5”) can get output such as
c;2010-09-09;3.89;3.95;3.88;3.91;4.19
c;2010-09-10;3.92;3.94;3.9;3.91;4.19
c;2010-09-13;3.96;4.01;3.96;3.99;4.97
c;2010-09-14;3.98;3.99;3.91;3.94;4.70
c;2010-09-15;3.92;3.93;3.9;3.92;3.35
c;2010-09-16;3.89;3.98;3.88;3.97;3.35
c;2010-09-17;4;4.02;3.95;3.95;3.61
not => #Analyse:0xb774af24
2)Analyse.vol(“c”,“5”).mean can get
=> 7.62
not NoMethodError: undefined method `mean’ for nil:NilClass
would you mind to help me to write code3?

On Fri, 24 Sep 2010 20:45:11 -0500, Pen T. [email protected]
wrote in [email protected]:

[snip]

Here goes:

2.here is my real code
real code1
require ‘rubygems’
require ‘mysql’
require ‘date’
class Analyse
@@result=[]

You’re still using a class variable rather than an instance variable.
You should understand the difference between the two. Try this
explanation:
http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

I would suggest replacing that line with:

def initialize
@result = []
end

This will instantiate and initialize an instance variable that you can
use to collect the results. Then change all references to “@@result
to “@result”.

def self.vol(symbol,cycle)

Change this to “def vol(symbol,cycle)” to make it an instance method
instead of a class method.

cycle=cycle.to_i
dbh = Mysql.real_connect(“localhost”, “root”, “******”)
dbh.query(“use stock;”)
result=dbh.query(“select symbol,date,open,high,low,close from
#{symbol} order by date asc;”)
compute=[]
result.each{|row| compute<<row.join(“;”)}

Why are you joining the values here only to split them up in the block
passed to each? The result should be a two dimensional array, which
you could index into easily.

compute.each.with_index{|row,idx|
row=row.split(“;”)

You’re reusing a variable name here. While scope may prevent
collisions with the variable of the same name in the outer loop, it’s
still a bad idea because it’s confusing to someone reading your code
(including a future you). Instead of “row” try “fields” or something
for the inner loop.

if idx> cycle-2 then
if row[4].to_f==0 then
row[6]=“nil”

Do you really mean to assign a string containing the characters “n”,
“i” and “l” to row[6]? The call to to_f in the mean method will
return 0.0 for that, the same as if you had set row[6] = nil.

end
line.each{|item|
amean<< item.chomp.split(“;”)[-1].to_f
}}
amean=amean.compact
format(“%.2f”,amean.inject(0){|s,n| s+n}/(amean.size.to_f)).to_f
end
end

[snip]

2)i want to make Analyse.vol(“c”,“5”).mean run
real code1 can get :
NoMethodError: undefined method `mean’ for nil:NilClass

[snip rest]

You’re trying to mix instance methods and class methods in a way that
won’t work. You really need to understand the difference between the
two concepts.

If you convert everything to instance methods and variables, then you
can have each of these functions return self, allowing chaining.
Example:

demo.rb

class A
def initialize
clear
end

def clear
@result = []
return self
end

def foo
10.times { @result << rand(1000) }
return self
end

def bar
@result.each { |item| puts item }
return self
end
end

C:\temp>irb
irb(main):001:0> require ‘demo’
=> true
irb(main):002:0> a = A.new
=> #<A:0x2df8c88 @result=[]>
irb(main):003:0> a.foo
=> #<A:0x2df8c88 @result=[154, 851, 93, 136, 183, 90, 34, 175, 345,
185]>
irb(main):004:0> a.bar
154
851
93
136
183
90
34
175
345
185
=> #<A:0x2df8c88 @result=[154, 851, 93, 136, 183, 90, 34, 175, 345,
185]>
irb(main):005:0> a.clear
=> #<A:0x2df8c88 @result=[]>
irb(main):006:0> a.foo.bar
9
878
775
994
876
60
917
29
39
610
=> #<A:0x2df8c88 @result=[9, 878, 775, 994, 876, 60, 917, 29, 39, 610]>
irb(main):007:0> a.clear.foo.bar
366
247
704
920
587
201
861
644
771
769
=> #<A:0x2df8c88 @result=[366, 247, 704, 920, 587, 201, 861, 644, 771,
769]>
irb(main):008:0>