Why the object doesn't respond to its method?


#1

Hi all,

I want to find out if an object responses to a method. while I can tell
that the excel object(in this script) responses to method ‘Visible or
visible’, my codes DO NOT come true. Any idea?

Thank very much,

Li

C:\Users\Alex>irb
irb(main):001:0> require ‘win32ole’
=> true
irb(main):002:0>
irb(main):003:0* excel=WIN32OLE.new(“excel.application”)
=> #WIN32OLE:0x389d638
irb(main):004:0> excel.Visible=true
=> true
irb(main):005:0> puts excel.respond_to?(“visible”)
false
=> nil
irb(main):006:0> puts excel.respond_to?(“Visible”)
false
=> nil
irb(main):007:0>
irb(main):008:0* puts excel.respond_to?(‘visible’)
false
=> nil
irb(main):009:0> puts excel.respond_to?(‘Visible’)
false
=> nil
irb(main):010:0>
irb(main):011:0* puts excel.respond_to?(:visible)
false
=> nil
irb(main):012:0> puts excel.respond_to?(:Visible)
false
=> nil
irb(main):013:0>


#2

Li Chen wrote:

Hi all,

I want to find out if an object responses to a method. while I can tell
that the excel object(in this script) responses to method ‘Visible or
visible’, my codes DO NOT come true. Any idea?

My guess is that WIN32OLE handles the call to Visibile via
method_missing and
does not redefine respond_to? to return true for methods handled by
method_missing.
Or, given that in your code you only ever called Visible= and never just
Visible, it might actually be the case that it does not respond to
Visible,
though that is admittedly unlikely.

HTH,
Sebastian


#3

Li Chen wrote:

Hi all,

I want to find out if an object responses to a method. while I can tell
that the excel object(in this script) responses to method ‘Visible or
visible’, my codes DO NOT come true. Any idea?

Hello. First, in your code you actually do not call the method Visible,
you call the method Visible= and it’s a big difference, generally.

But you won’t find the method Visible= neither, as, as said above, the
capitalised ole methods are handled by method_missing. You can see a
list of ole methods like this:
excel.ole_methods
This gives an array of all the methods, where you can see Visible twice,
once it is the method Visible and once Visible=, but you cannot tell one
from another at a glance. To get just a list of, say, setters, to find
the method Visible=, you write excel.ole_put_methods, and to get a list
of getters (or probably other methods, but with exclusion of setters)
you write excel.ole_get_methods.

Now there’s one more problem - the list doesn’t contain strings, but
WIN32OLE_METHOD objects. I do not actually know how to handle this, but
this is how you can check if Visible= is among the methods of the
object:
excel.ole_put_methods.find{|m| m.name==“Visible”}
The above line returns nil iff excel does not respond to Visible=.

TPR.


#4

Li Chen wrote:

Hi Thomas,

I find the method “Visible” but not"Visible=" here but the
respond_to?(“Visible”) still return false. I don’t know how to explain
it.

This is correct. As it has been said, the respond_to? doesn’t work with
ole methods as they are served by metod_missing, which means that there
are no such methods defined for this object. A sample to illustrate
this:

class K
def method_missing(m)
puts “Inside qwe” if m==:qwe
end
end
k=K::new
k.respond_to? :qwe #=> false
k.qwe ## prints: Inside qwe

So you are not able to check if there is an ole method using
respond_to?. I hoped I stated it clearly in the above post, but
apparently not.

Now the other problem: when you write excel.Visible=true, you call the
method Visible=, but, as already stated, respond_to? :Visible= will not
detect the presence of this method. You have to look for this method in
the ole_methods table.

In general, ole methods are divided into two groups - setters (those
that you call with = at the end, like Visible=) and other methods (those
without =, like when you call excel.Visible (it returns the current
status) or any other of similar methods. But in the ole_methods table,
they are all reported without the =, that’s why you see two elements
Visible in the table returned by excel.ole_methods. To distinguish
between them, it’s better to look up the method you are looking for in
the specific ole methods table, so: you look for setters inside
excel.ole_put_methods, and for other methods inside
excel.ole_get_methods. So, to check if there is a method called Visible
(without =, the getter), you run this code:
excel.ole_get_methods.find{|m| m.name==“Visible”}
It returns nil if the method is not present and calling excel.Visible
will raise an error, and a non-nil value if the ole method is present.
But if you want to check if there is a setter, that is, a method named
Visible=, then you have to look it up in the other table:
excel.ole_put_methods.find{|m| m.name==“Visible”}
Again, nil means no method, non-nil means that method Visible= is
present for the object. Note that in the last code line there is no
“Visible=”, but “Visible”, and this is because ole setters in the ole
methods table do not have the = in name, even though they are setters.
And that’s the very reason why we must look up setters and getters in
two distinct tables.

If you want, you can add a method like ole_respond_to? to the class
WIN32OLE, like this:

class WIN32OLE
def ole_respond_to?(m)
m=m.to_s
if m[-1]==?=
m=m[0…-1]
table=ole_put_methods
else
table=ole_get_methods
end
!!table.find{|om| om.to_s==m}
end
end

excel.ole_respond_to? :Visible= #=> true

Not tested carefully, so rather don’t use it unless you can understand
it.

Hope this helps.

TPR.


#5

Hi Thomas,

Thank you very much for the detailed explanation.

It is my understanding from your reply that I should look for
ole_get_methods for the methods of “getter” and look for ole_put_methods
for methods of “setter”.

Question 1: In the following scripts both getters and setters have
method “Voice” but respond_to?() responses to both of them as “fasle”.
It seems to me that respond_to?() cannot detect the methods in either
getters or setters. Is it true? If this is case what methods can be
detected by respond_to?() ?

Question 2: There are ole_put_methods, ole_get_methods, and ole_methods
in WIN32OLE. From your post now I know the differences among
ole_put_methods and ole_get_methods. But how about ole_methods? I only
know it will return more methods. And most of them cannot detected by
respond_to?(),either.

Li

C:\Users\Alex>irb
irb(main):001:0> require ‘win32ole’
=> true
irb(main):002:0>
irb(main):003:0* voice=WIN32OLE.new(‘SAPI.SpVoice’)
=> #WIN32OLE:0x280e934
irb(main):004:0>
irb(main):005:0* puts “1-getters”
1-getters
=> nil
irb(main):006:0> puts

=> nil
irb(main):007:0> puts voice.ole_get_methods.sort{|x,y|x.to_s<=>y.to_s}
AlertBoundary
AllowAudioOutputFormatChangesOnNextSet
AudioOutput
AudioOutputStream
EventInterests
Priority
Rate
Status
SynchronousSpeakTimeout
Voice
Volume
=> nil
irb(main):008:0> puts

=> nil
irb(main):009:0>
irb(main):010:0* puts “2-setters=”
2-setters=
=> nil
irb(main):011:0> puts

=> nil
irb(main):012:0> puts voice.ole_put_methods.sort{|x,y|x.to_s<=>y.to_s}
AlertBoundary
AllowAudioOutputFormatChangesOnNextSet
AudioOutput
AudioOutputStream
EventInterests
Priority
Rate
SynchronousSpeakTimeout
Voice
Volume
=> nil
irb(main):013:0> puts

=> nil
irb(main):014:0>
irb(main):015:0* puts “respond to 1-getters”
respond to 1-getters
=> nil
irb(main):016:0> puts voice.respond_to?(“Voice”)
false
=> nil
irb(main):017:0>
irb(main):018:0* puts “respond to 2-setters=”
respond to 2-setters=
=> nil
irb(main):019:0> puts voice.respond_to?(“Voice”)
false
=> nil
irb(main):020:0>


#6

Thomas B. wrote:

Now there’s one more problem - the list doesn’t contain strings, but
WIN32OLE_METHOD objects. I do not actually know how to handle this, but
this is how you can check if Visible= is among the methods of the
object:
excel.ole_put_methods.find{|m| m.name==“Visible”}
The above line returns nil iff excel does not respond to Visible=.

TPR.

Hi Thomas,

I find the method “Visible” but not"Visible=" here but the
respond_to?(“Visible”) still return false. I don’t know how to explain
it.

Li

C:\Users\Alex>irb
irb(main):001:0> require ‘win32ole’
=> true
irb(main):002:0>
irb(main):003:0* excel=WIN32OLE.new(“excel.application”)
=> #WIN32OLE:0x398d638
irb(main):004:0>
irb(main):005:0*
irb(main):006:0* puts “first method”
first method
=> nil
irb(main):007:0> excel.ole_get_methods.each do |e|
irb(main):008:1* if “#{e}”==“Visible”
irb(main):009:2> puts “find Visible”
irb(main):010:2> elsif “#{e}”==“Visible=”
irb(main):011:2> puts “find Visible=”
irb(main):012:2> else
irb(main):013:2* #puts “no method”
irb(main):014:2* end
irb(main):015:1> end
find Visible
=> [Application, …MANY METHODS HERE… HighQualityModeForGraphics]
irb(main):016:0>
irb(main):017:0* puts “second methods”
second methods
=> nil
irb(main):018:0> excel.ole_put_methods.each do |e|
irb(main):019:1* if “#{e}”==“Visible”
irb(main):020:2> puts “find Visible”
irb(main):021:2> elsif “#{e}”==“Visible=”
irb(main):022:2> puts “find Visible=”
irb(main):023:2> else
irb(main):024:2* #puts “no method”
irb(main):025:2* end
irb(main):026:1>
irb(main):027:1* end
find Visible
=> [ActivePrinter,…MANY METHODS HERE…
LargeOperationCellThousandCount,HighQualityModeForGraphics]
irb(main):028:0>
irb(main):029:0* puts excel.respond_to?(“Visible”)
false
=> nil
irb(main):030:0>


#7

HI Thomas,

Thank you very much for your time and the help.

Li


#8

Li Chen wrote:

It seems to me that respond_to?() cannot detect the methods in either
getters or setters. Is it true? If this is case what methods can be
detected by respond_to?() ?

The ole methods cannot be detected by respond_to?. This is exactly what
I have been trying to communicate to you, since the first post.

In general, respond_to? detects all methods of all object. Ole objects
are sort of exception here - ole methods are not detected by
respond_to?, but other methods are. If you have any object of any of the
standard Ruby classes, it will always work as expected - respond_to?
returns true iff the object responds to this method.

But how about ole_methods? I only
know it will return more methods. And most of them cannot detected by
respond_to?(),either.

It just returns all the ole methods, both setters and non-setters, all
messed up together. You will see that excel.ole_methods includes a
method named Visible twice - one of them is the setter and the other is
the getter. The only way to tell which is which (the only that I know
for now, but note that I was never really working with ole objects) is
to call the method’s return_type method, like this:

irb(main):075:0> voice.ole_methods.select{|m| m.to_s==“Voice”}.each{|m|
p m.return_type_detail}
[“PTR”, “USERDEFINED”, “ISpeechObjectToken”]
[“VOID”]

But I don’t know how to interpret the results. But we at least see now
that these are two distinct methods, even though both are reported to be
named Voice.

TPR.


#9

Hi Thomas,

I guess I figure out why the object doesn’t respond to its method in
win32ole.

Based on my other post this week someone points to me that I need to
pass more parameters into the method.

Please see the following scripts:
Ruby will complain if I write fs.Open(file) but it works if another
parameter 2 is passed.

But right now I still can’t figure out how to pass the right
parameter(in this sample is 2).

Li

###############################
require ‘win32ole’
fs=WIN32OLE.new(‘SAPI.SpFileStream’)

p fs.ole_method(“open”).params

file=‘c:/test.txt’

fs.Open(file,2) #least two params
fs.write(“data”)
fs.Close