How to destroy Ruby object?
Other than hacking the underlying C code, no. Garbage collection is managed by the runtime so you don't have to worry about it. Here is a decent reference on the algorithm in Ruby 2.0.
Once you have no more references to the object in memory, the garbage collector will go to work. You should be fine.
Ruby: deleting object while looping over list with that object
In Ruby you will actually find a glitch if you do what you are saying.
Try this:
objects = [1,2,3,4]
objects.each { |el| objects.delete(el) }
=> [2, 4]
You would expect the result to be an empty array, but is not. We are messing up with the elements of the arr
and each
gets confused, because the length of the array has changed. The each iterator looks something like this in pseudocode:
count = 0
while length(objects) > count
yield objects[count]
count + 1
end
So, in the example I shown above, the reason why we get [2, 4]
can be explained on a step by step analysis on what objects.each { |el| objects.delete(el) }
is doing:
- We start with 4 (length of objects) > 0.
- Number 1 is yielded, and deleted.
- count = 1
- 3 (length of objects) > 1
- Number 3 is yielded and deleted.
- count = 2
- 2 (length of objects) is not bigger than count
- We are done, so we have
[2, 4]
There is a better way to do what you are trying, by using delete_if:
new_objects = objects.delete_if {|o| o.withinBounds }
Remove/delete object from array in Ruby based on attribute value
You can use the #reject
method to return the array without objects whose :units
equals 0
:
result.reject { |hash| hash[:units] == 0 }
There's also #reject!
and #delete_if
, which can be used in the same way as above but both modify the array in place.
Hope this helps!
Deleting an object in Ruby
Right now, they will never be garbage collected, as you are holding a reference in @@all_instances
. You could use a finalizer to get the result you want:
class Vehicle
class << self
attr_accessor :count
def finalize(id)
@count -= 1
end
def all #returns an array of all Vehicle objects
ObjectSpace.each_object(Vehicle).to_a
end
end
Vehicle.count ||= 0
def initialize
Vehicle.count += 1
ObjectSpace.define_finalizer(self, Vehicle.method(:finalize))
end
end
100.times{Vehicle.new}
p Vehicle.count # => 100
ObjectSpace.garbage_collect
p Vehicle.count # => 1, not sure why
p Vehicle.all # => [#<Vehicle:0x0000010208e730>]
If you run this code, you will see that it "works", except that there remains one Vehicle that is not garbage collected. I'm not sure why that is.
Your count
method could be also defined more simply by returning ObjectSpace.each_object(Vehicle).count
Finally, if you really want to maintain a list of existing Vehicles, you need to store their ID and use ObjectSpace._id2ref
:
require 'set'
class Vehicle
class << self
def finalize(id)
@ids.delete(id)
end
def register(obj)
@ids ||= Set.new
@ids << obj.object_id
ObjectSpace.define_finalizer(obj, method(:finalize))
end
def all #returns an array of all Vehicle objects
@ids.map{|id| ObjectSpace._id2ref(id)}
end
def count
@ids.size
end
end
def initialize
Vehicle.register(self)
end
end
Deleting an instance of a class via a method of that class
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).
How do you delete an ActiveRecord object?
It's destroy
and destroy_all
methods, like
user.destroy
User.find(15).destroy
User.destroy(15)
User.where(age: 20).destroy_all
User.destroy_all(age: 20)
Alternatively you can use delete
and delete_all
which won't enforce :before_destroy
and :after_destroy
callbacks or any dependent association options.
User.delete_all(condition: 'value')
will allow you to delete records
without a primary key
Note: from @hammady's comment, user.destroy
won't work if User model has no primary key.
Note 2: From @pavel-chuchuva's comment, destroy_all
with conditions and delete_all
with conditions has been deprecated in Rails 5.1 - see guides.rubyonrails.org/5_1_release_notes.html
Remove unwanted attributes from an object in ruby
u.attributes.except("first_name", "last_name")
Remove Object from Active Record Array
First question, if you don't want the all records, then why even return them from the DB? Why not use a where clause to filter results:
@products = Product.where(<CONDITIONS>)
Second, if you insist on returning all results then filtering, use a .reject
block:
@products = Product.all.reject { |p| <CONDITION> }
Related Topics
Overriding Model in Gem, Adding Callback and Methods
Rails 5 - Using Polymorphic Associations - Rendering the Views
How to Click a Link in a Table Based on the Text in a Row
Call Next on Ruby Loop from External Method
How to Stub Out Warden/Devise with Rspec in Capybara Test
Case-Insensitive Find_Or_Create_By_Whatever
Ruby on Rails Global Activerecord::Enum
Is It Acceptable Having Parameter in Class Constructor
Changing Http Status Message Using Sinatra
Rails Routing - Custom Routes for Resources
What's the Best Way to Return an Enumerator::Lazy When Your Class Doesn't Define #Each
Linking Two Models in a Multi-Model Form
Require Ruby File Without .Rb Extension
How to Prevent Rails Controller Generator to Modify Config/Routes.Rb