Deleting an instance of a class via a method of that class - ruby

I have a class for pieces on a board. I want to be able to delete an instance of Piece so that anything else in the program that points to that piece will just point to nil.
Here's the very basic code version of what I want to do:
piece = Piece.new
variable = piece
variable #=> <Piece:0x0000000xxxxxxxx>
piece.delete
variable #=> nil
This seems like a very basic task so I feel like I'm missing something obvious. I've tried creating a delete method for the class with "self = nil", but this returns an error ("Can't change the value of self").
So far I have just worked around this by updating the other things that point to the object in my 'delete' method, but it seems like there should be a better way.

This is not possible.
Firstly, Ruby is an object-oriented language, which means that all manipulation is done via messages to objects, and all that is manipulated are objects. Variables are not objects, therefore you cannot manipulate them. (The only things you can do with variables are assign a value to them and dereference them.)
And even if you could manipulate variables, you would still need to hunt down every single reference to the object in question and remove it, in order for the object to be eligible for "deletion" (i.e. garbage collection).

Related

In Ruby, what are the use cases for adding methods to an instance's singleton class?

Thanks to some other posts and reading, I understand singleton/meta classes. And I understand why we'd want to use them on a class. But I still don't understand why we'd want to use them on instance objects. And I've yet to see it in practice.
I'm referring to something like this:
class Vehicle
def odometer_reading
# some code
end
end
my_car = Vehicle.new
def my_car.open_door
# some code
end
At first thought, this seems like a bad idea as it would lead to difficulties in understanding the code and debugging.
Why would we want to do this? What are some examples of when this is a good idea?
One example is using it for testing purposes: creating mock and double objects, stubbing methods. Debugging is somewhere nearby: re-defining the logging method for a specific object that you suspect is mis-behaving, so that the log info is printed directly to console (or more info is printed) during the debug session.
Another example is dealing with special cases - instead of inheritance you can do just that. Starting from a classical example if you use two types of Employees, say, Engineers and SalesPersons, for which the rules of compensation calculation are different, you can put the common logic into the Employee class, then inherit the other two classes from it and implement their own calculate_salary methods there. Now, if there is an outlier - a star salesman that you have agreed to a different compensation scheme with, a CEO with a very special scheme, etc - instead of creating a whole sub-class for this special employee, you can just define this method for a specific object representing that employee.
The third example is dealing with an object lifecycle and performance considerations. Instead of having a long case of various states in some processing method. E.g. for a file-reading class that transparently caches the entire file in the background (I know a too-simplistic-for-real-life approach, but just as a model) all read requests while the file is not entirely read should check if the requested data is already in the cache or should be read from disk. Once the file is fully read they always go from the cache. Instead of having the if (case if there are more states) to deal with this you could simply re-define the read method at the object-level once the file is fully read to the cache. For this simple example it doesn't lead to any sizable performance benefit (if any benefit at all), but for more complex cases that may be worth it.
You wouldn't add them using def, that's a rather rigid way of doing it, but instead by using something like define_method or extend.
Although this is not the sort of thing you'd do on a routine basis, it does mean you can do some rather unusual things. ActiveRecord in Rails produces results in the form of an Array with additional methods added on to perform other operations.
An Object-Relationship Mapper would be a case where you'd probably want to do this. Sometimes, depending on how you fetch a record, the methods available differ significantly. Being able to add those dynamically means each fetched object can be completely customized even if they have the same class and general-purpose methods.
Another example: You have an array of hashes and you want each hash to have a method-call getter and setter. Something like:
user = HashOnSteroids.new(name: 'John')
user[:name] # => 'John'
user[:name] = 'Joe'
user.name # => 'Joe'
user.name = 'John'
user.set(name: 'Jim', age: 5)
This means you cannot write standard method definitions in the class as each hash will have a different set of keys (method names). This means you have to resort to defining singleton methods so each object has its own set of methods (not a pack of shared methods).
Warning: Using singleton methods for this use case is highly inefficient. A sneaky method_missing is faster and uses way less memory as it doesn't have to allocate a billion of proc objects.

Ruby: marshal and unmarshal a variable, not an instance

OK, Ruby gurus, this is a hard one to describe in the title, so bear with me for this explanation:
I'm looking to pass a string that represents a variable: not an instance, not the collection of properties that make up an object, but the actual variable: the handle to the object.
The reason for this is that I am dealing with resources that can be located on the filesystem, on the network, or in-memory. I want to create URI handler that can handle each of these in a consistent manner, so I can have schemes like eg.
file://
http://
ftp://
inmemory://
you get the idea. It's the last one that I'm trying to figure out: is there some way to get a string representation of a reference to an object in Ruby, and then use that string to create a new reference? I'm truly interested in marshalling the reference, not the object. Ideally there would be something like taking Object#object_id, which is easy enough to get, and using it to create a new variable elsewhere that refers to the same object. I'm aware that this could be really fragile and so is an unusual use case: it only works within one Ruby process for as long as there is an existing variable to keep the object from being garbage collected, but those are both true for the inmemory scheme I'm developing.
The only alternatives I can think of are:
marshal the whole object and cram it into the URI, but that won't work because the data in the object is an image buffer - very large
Create a global or singleton purgatory area to store a variable for retrieval later using e.g. a hash of object_id:variable pairs. This is a bit smelly, but would work.
Any other thoughts, StackOverflowers?
There's ObjectSpace._id2ref :
f = Foo.new #=> #<Foo:0x10036c9b8>
f.object_id #=> 2149278940
ObjectSpace._id2ref(2149278940) #=> #<Foo:0x10036c9b8>
In addition to the caveats about garbage collection ObjectSpace carries a large performance penalty in jruby (so much so that it's disabled by default)
Variables aren't objects in Ruby. You not only cannot marshal/unmarshal them, you can't do anything with them. You can only do something with objects, which variables aren't.
(It would be really nice if they were objects, though!)
You could look into MagLev which is an alternative Ruby implementation built on top of VMware's Gemstone. It has a distributes object model wiht might suit your use-case.
Objects are saved in the central Gemstne instance (with some nifty caching) and can be accessed by any number of remote worker instances. That way, any of the workers act on the same object space and can access the very same objects simultaneously. That way, you can even do things like having the global Garbage Collector running on a single Ruby instance or seamlessly moving execution at any point to different nodes (while preserving all the stack frames) using Continuations.

How can I update an already instantiated Ruby object with YAML?

Basically, I have an instance of a Ruby object already but want to update whatever instance variables I can from yaml. There is a to_yaml function that will dump my object to yaml. I'm looking for something in the reverse. For example, my_obj.from_yaml(yaml_stuff) and have it update instance variables from the yaml passed in.
Would I need to, in my from_yaml function, use YAML::load and copy each instance variable? Is there a function I can use to quickly copy those variables without much typing if that is the case?
Does Ruby's yaml library have something already where I can pass it the object and the yaml and it'll just do what I want it to do?
Editing for clarity
This is a simple object that will store and load very simple yaml compatible types such as strings and integers.
What I ended up doing
Although I answered this question I wanted to add what I ended up doing, my Object monkey patch
class Object
def from_yaml(yml)
if (yml.nil?)
return
end
yml.instance_variables.each do |iv|
if (self.instance_variable_defined?(iv))
self.instance_variable_set(iv, yml.instance_variable_get(iv))
end
end
end
end
Your question is not clear enough. Which class are you talking about? What kind of YAML documents? You can't have everything serialized to and from YAML.
Let's assume that your object just has a set of instance variables of simple, YAML-compatible types, such as strings, numbers and symbols.
In that case, you can generally, write from_yaml method, which would load YAML file into a hash of key->value pairs, iterate through it and update every instance variable named key with value. Does that seem useful, and if it does, do you need help writing such method?
Edit:
There is no need for you to keep your object state in a hash - you can still use ivars and attr_accessors - just open up a new module (say YamlUpdateable), implement a from_yaml method which would update your ivars from a hash deserialized from YAML, and include the module in whichever class you want to deserialize from YAML.
As far as I know, there's nothing like that included with the YAML library itself; it's mostly meant for dumping and reading data, not keeping it up-to-date in memory and on disk. If you're planning to keep data in memory and on disk synced with each other with minimal hassle, have you considered a data persistence library like ActiveRecord or Stone?
If you're still keen on using the YAML library, and assuming you don't have many different classes to persist, it might make sense to simply write a small "updater" method that updates an object of that class given a similar object. Or you could rework your application to make sure you can simply reload all the objects from the YAML without having to update them (i.e., dump the old objects and create new ones).
The other option is to use metaprogramming to read into an object's properties and update them accordingly, but that seems error-prone and dangerous.
What you are looking for is the merge command.
// fetch yaml file
yml = YAML.load_file("path/to/file.yml")
// merge variables
my_obj.merge(yml)

Ruby, Candy and SQL-like mongo stuff

So Candy is a really simple library for interacting with Mongo in Ruby.
My poor SQL brain is having a tough time figuring out how I should map out this problem:
There are users, there are things. Each thing was made by one user, but should be accessible to a subset of all users (specified within the thing). Leaving the specification of user out of the way for now, how would I get a list of all things that user X has access to?
class Thing
include Candy::Piece
end
class Things
include Candy::Collection
collects :thing
end
Should I assign the allowed users to a thing like this? (lets just use strings to reference users for now)
t = Thing.new
t.allowed = ['X','Y','Z']
This seems about right to me, which would make me want to do:
Things.find(allowed:'X')
but it's not quite working…
NoMethodError: undefined method ‘call’ for {:allowed=>"X"}:Hash
any ideas?
I'm really sorry I took so long to catch this and respond. This might be too late for your purposes, but:
Candy doesn't implement a find method. This is on purpose: if an object represents a collection, every access is implicitly finding something in that collection. It's the same reason there is no save method. If the mapping is truly transparent, verbs that mean "Do this in the database" shouldn't be necessary.
So to do what you want, you could either just make a new Things object with the scope passed on creation:
x_is_allowed = Things.new(allowed: 'X')
...or you could save a step and do it by class method:
x_is_allowed = Things.allowed('X')
...or you could start with the whole collection and limit it by attribute later:
things = Things.new
x_is_allowed = things.allowed('X')
So... Um. All of those will work. But. I have to warn you that I'm really not happy with the general usability of Candy right now, and of collections and array fields in particular. The biggest problem is accessors: the [] method isn't working like you'd expect, so you end up having to call to_a and refresh and other things that feel sticky and unpleasant.
This needs to be fixed, and I will do so as soon as I finish the driver rewrite (a related project called Crunch). In the short term, Candy is probably best viewed as an experiment for the adventurous, and I can't guarantee it'll save time until the interface is locked down a bit better. I'm sorry about that.

Retain information in cocoa?

I'm still new to Cocoa and don't know much about memory management. I read up on Apple's documentation but I'm still confused. My question is if I set the value of a variable in a - (void)dowhatever when dowhatever ends, will the contents of the variable be erased? If so is there a method (without writing to a file) that I can use to retain the variable contents?
Thanks for any help
My question is if I set the value of a variable in a - (void)dowhatever when the void ends, …
void is a type. It has no beginning and no end.
Specifically, it's the return type of the dowhatever method. If dowhatever returned a value, the type of that return value would be where you have void; it would say, for example, - (NSUInteger) doWhatever. Having void there means that the method does not return a value.
See also the Objective-C 2.0 Programming Language document.
… will the contents of the variable be erased?
If it's a local variable, then the variable will cease to exist when the method returns.
An instance variable exists as long as the instance (object) that the variable is a part of exists—that is, until the instance is deallocated.
Instance variables are also covered in the Objective-C documentation.
If so is there a method (without writing to a file) that I can use to retain the variable contents?
If you simply need to return the object to your caller, retain it and autorelease it. See the Memory Management Programming Guide for Cocoa for more info.
If that's not what you're doing, then the question becomes why you need the object to stay alive.
Think in terms of objects: An object may own certain other objects, and has an instance variable for every object it owns*. As long as you have your ownerships straight and uphold them in code, objects' lifetimes just work.
If object A needs another object B, then A should own B. This ownership isn't exclusive; it can co-own B. But it needs to at least co-own B; B will remain alive as long as it has at least one owner.
That's also covered in the Memory Management Guide. For other examples of relationships between objects, you should flip through the Cocoa Fundamentals Guide, particularly the chapter on Cocoa's design patterns, and you may want to look through sample code to see those patterns demonstrated in practice.
*It can also have instance variables for objects it doesn't own, such as delegates. You can have an instance variable for an object you don't own, but if you do own it, you should have an instance variable for it.

Resources