I have created a class in visual works smalltalk, added a method (for example: list) but when I called it in workspace it shows error like message not understood #list.
Thank You in Advance.
I'm sure you sent the message to the class and not to the instance, so you need to send #new first.
If you create a Class like "Foo" and add an instance method like "bar", you need to evaluate:
Foo new bar
Related
I have an app which uses Ruby 1.8. 6 in a Rails 2.2.2 app.
It has many definitions of the method url_for in various parts of the code base (classes, modules etc).
When debugging, I'd like to see in the log which method handles a specific call to url_for. E.g.,
foo = "bar"
baz = url_for(foo)
#would like to log the location of the url_for method which actually
#handled the call, here.
It's fine if the only way to do this is to raise an exception inside url_for and look at the stack trace, eg
baz = url_for(something_which_wont_raise_here_but_will_raise_inside_the_url_for_method)
To go further, what if the method is being called on an instance of a (heavily patched) class:
foo = #baz.bar("qux")
EDIT: I didn't specify that it was Ruby 1.8.6 in my question, and it looks like i can't use the .source_location method. Very sorry about not specifying the version earlier! Does anyone have any other ideas?
It sounds like you want to do
method(:url_for)
to get a Method object, and then use source_location to find out where it was defined
You can use method and source_location methods chain to get the location of the method definition.
For example:
If you do:
method(:url_for).owner
It will give you the module/class in which the method is defined. This should be enough to let you identify the method (unless the same method is redundantly defined in the same module multiple times). You can then look at the definition of url_for in that module/class.
I have this idea for a client/server archetype where the server would hold a hash of Marshal.dump'ed class objects along with their version numbers. Then the client could query the server concerning the version number and import the newer version of the class before instantiating it:
class Stuff
def methods
gibberish
end
end
$obj_hash["Stuff"] = [3.0, Marshal.dump(Stuff)]
The problem I'm running into is that Ruby doesn't seem to want to allow me to Marshal.load the data once I've downloaded it from the server because the class and its methods don't exist in the client. If I bypass this by creating a 'dummy' class I'm then unable to replace the dummy class with the Marshal.load'ed data. If I simply try to use the loaded data as a class it functions according to the contents of the dummy class rather than the downloaded one.
Is there another way to go about this? If not then I guess I could just gz the code and then eval it at the other end, but I'm trying to avoid using eval or sending easily decipherable code over the line.
Thanks in advance for any advice.
Look at what happens.
class Stuff
def methods
"foo"
end
end
ruby-1.8.7-p352 :001 > Marshal.dump(Stuff)
=> "\004\bc\bStuff"
Notice how it says nothing about "methods" or "foo." If the server isn't sending that code down the wire, how is the client supposed to know what Stuff#methods should do?
It won't. :)
To do what you want to do, you'll have to send down the code itself and eval it. You'll have to implement the versioning logic yourself, of course, and "really re-define" the classes (not just monkey-patch) them.
See are you allowed to redefine a class in ruby? or is this just in irb
first sorry for my poor english...I've a doubt..I'm reading the FXRuby for the pragmatic programmer..and I saw this code
require 'fox16'
include Fox
class HelloWindow < FXMainWindow
def initialize(app)
super(app, "Hello, World!" , :width => 200, :height => 100)
end
def create
super
show(PLACEMENT_SCREEN)
end
end
app = FXApp.new
HelloWindow.new(app)
app.create
app.run
It's a very basic example...actually It's he first example..but I'm so noob than I don't understand it:
app is a FXAPP object..
now I create a HelloWindow object and pass my FXApp object named "app"
so far so good
but now...in the book write app.create
I'm calling the "create" method inside FXApp class...or not?..
why when I call app.create..ruby call the create method inside HelloWindow?..app is a very different object than HelloWindow class and I could can call an anscestor method (like when I use super) but not at the inverse way...
why they don't call it something like this
helloobject=HelloWindow.new(app)
helloobject.create
this way I calling the create method inside HelloWindows class..and it is descendent from FXMainWindows
I hope than you can understand (sorry for my bad english) and can help me
thanks so much
I don't know anything about FXRuby, but I answer your questions about the Ruby side of things.
When Ruby executes app.create, it will call the create method inside the FXApp class because app's type is FXApp (assuming that there is no create method defined for the singleton class of app).
When you call app.create, there is probably some code in the FXApp class to calls create on all of the windows in the app, so that's how your window's create function gets called. If you want to really find out how your window's create function is being called, try adding raise "hello" to it and see if you get a backtrace of the exception.
I don't really know the answer to your last question because it has to do with the design of the FXRuby library. But conceptually it seems like calling app.create and window.create are very different things. If you want to run the app, you should create it first. Simply creating one window isn't good enough.
I am trying to understand the working of ruby open classes. In particular how does a method gets added to an existing class?
There must be some logic applied to identify if the class already exists.
Can someone please explain the concept.
Thanks in advance.
Class names are constants, so it's fairly easy to see if a class name already exists:
Object.constants.grep(/Array/) #=> ["Array"]
So if a class is already defined (Object.const_get('Array').is_a? Class) the methods get added to it, otherwise a new class gets defined. To be a bit more precise this happens on the C side of Ruby, but is more or less what it boils down to.
Underneath Ruby, there are messages.
Suppose you've a class A, and a is an instance of A. There actually are several classes involved:
Basic Object
-> Object
-> A
-> a
When you call method foo on a, what's really happening is you're sending the message "call foo" to a. It checks if the instance method is defined for a (as in, the singleton/eigenclass), then tries instance methods of A, then Object, and finally Basic Object. If all else fails, the VM sends a new message (i.e. "method not found") and the procedure starts again until it gets caught (by default, it raises an exception).
You can add a new method (i.e. a message handler) to any of the classes in the hierarchy, in order to change the behavior of a. If you add an instance method to A or Object, then a will have it. If you add a method to a only (i.e. def a.bar; 'bar'; end), then other instances of A will have it.
Ruby's classes (I'd argue it would more appropriate to say ruby's objects) are open in the sense that you can add these new methods, i.e. message handlers, at any point in time -- including long after they've been defined.
In my app, I have
VeryUniqueModule::Foo
# and…
VeryUniqueModule::Bar
Foo and Bar are each for a different service. Part of my app has to dynamically figure out which module to refer to, which it capably does like so:
def service_api
# #relevant_object.service is a string that is either 'Foo' or 'Bar'
VeryUniqueModule.const_get(#relevant_object.service)
end
More on this later.
I just updated a library, and it now has its own top-level Foo class (which is bad design on its part). Now when I try to invoke #relevant_object.service_api::A_CONSTANT, my app complains that the library's Foo does not have A_CONSTANT.
Back to service_api above -- I thought that const_get was returning the class itself. In fact I know it is. If I fire it up in irb everything is as expected -- the return value is the class itself, and I can invoke things on the class. So…
How is it possible that there's a namespace conflict in the first place? I'm looking for A_CONSTANT on the Class object returned by service_api, not on a string that I'm evaling or something funky like that -- there shouldn't be any namespace issues, I'm referring directly to an object!
If this is indeed a problem, how can I fix service_api so that it will return the, erm, "full path"?
You might try this:
VeryUniqueModule.const_get('::VeryUniqueModule::' + #relevant_object.service)
And if that doesn't work, you could try bypassing service_api and doing this wherever you need A_CONSTANT:
Object.const_get('::VeryUniqueModule::' + #relevant_object.service + '::A_CONSTANT')
Note the :: before VeryUniqueModule. I don't think it's strictly necessary in this case, but it could be useful in that it guarantees Ruby will look for VeryUniqueModule in the global namespace and not inside some other module.