1

I have a ruby class like this:

class Table
  def initialize(name)
    @name = name
    @columns = {}
  end
end

I'm creating different objects:

table_1 = Table.new("First")
table_2 = Table.new("Second")
table_3 = Table.new("Third")

How can I find among the objects of the Table class the object having "Second" as name attribute ?

5 Answers 5

2

Without creating any additional structures of data:

ObjectSpace.each_object(Table).find { |object| object.instance_variable_get(:@name) == "Second" }
=> #<Table:0x007f9f912b0ce0 @columns={}, @name="Second">
Sign up to request clarification or add additional context in comments.

6 Comments

Further question, how can I distinguish garbage from non-garbage objects?
And how can I select only non-garbage objects without forcing a gc?
@Aetherus, I do not yet have discovered the full power of ObjectSpace and GC, so can't answer the question about distinquishing between garbage and non-garbage objects.
But, .instance_variable_get(:@name) - for what here? I think, ObjectSpace.each_object(Table).find { |object| object.name == "Second" } will work the same in this example, no?
@AlexGolubenko no, there is no attr_reader for @name instance variable :)
|
1

You can keep a reference to an array of instances in the class.

class Table
  @instances = []
  class << self
    attr_accessor :instances
  end

  def initialize(name)
    @name = name
    @columns = {}
    self.class.instances << self
  end
end

Then you can get all the instances by

Table.instances

This, however, will prevent all the Table objects being garbage collected, so it is only feasible if you have only a small amount of Tables and that amount never grows, otherwise you'll have a memory leak.

4 Comments

@Andrey's solution is the shortest but this one allowed me to keep objects
Nice solution! @GrahamSlick just a short note: you never said in your question that you wanted to keep objects ;) But good you've found a suitable solution!
@AndreyDeineko I know bc I only realized it was removing objects once I implemented yours :D Sorry about that, but thanks a lot for your help too
@GrahamSlick :D as I say, no probs, glad to help :)
1

Let's add a getter method for the name attribute

class Table
  attr_reader :name

  def initialize(name)
    @name = name
    @columns = {}
  end
end

Now, if you have an array of Table objects

arr = [Table.new("First"), Table.new("Second"), Table.new("Third")]

You can find by name

arr.find { |table| table.name == "Second" }
 => #<Table:0x007f862107eb18 @name="Second", @columns={}> 

Comments

1

You can use enumerable find or any similar method from the enumerable module:

class Table
  attr_reader :name
  def initialize(name)
    @name = name
    @columns = {}
  end
end

table_1 = Table.new("First")
table_2 = Table.new("Second")
table_3 = Table.new("Third")

x = [table_1, table_2, table_3].find { |t| t.name == "Second" }

puts x.name => "Second"

Comments

1

Let's say we have reader on name in Table:

class Table
  attr_reader :name

  def initialize(name)
    @name = name
    @columns = {}
  end
end

I'd encourage you to store these Table classes' objects in a list/array:

table_1 = Table.new("First")
table_2 = Table.new("Second")
table_3 = Table.new("Third")

tables = [table_1, table_2, table_3]

Which can then be used for finding it using find(as mentioned in one of the answers) or detect:

tables.detect { |t| t.name == "Second" } #=> table_2 object

If you'd like to go one more step ahead then we can have another class maintaining this array:

class TableList
  attr_reader :tables
  def initialize
    @tables = tables
  end

  def add(table)
    @tables << table
  end

  def find_by_name(name)
    tables.detect{ |table| table.name == name }
  end
end

Which can then be used as:

table_1 = Table.new("First")
table_2 = Table.new("Second")
table_3 = Table.new("Third")
table_list = TableList.new
table_list.add(table_1)
table_list.add(table_2)
table_list.add(table_3)

table_list.find_by_name('Second') #=> table_2 object

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.