How to declare Class Instance Variable in inherited class automatically - ruby

I am using Class Inheritance Variables in Ruby to keep track of the number of instances I've created so far. To keep my code DRY, I implemented most of the logic in a base class that all my other classes inherit from.
class Entity
#instance_counter = 0
class << self
attr_accessor :instance_counter
end
def initialize
self.class.instance_counter += 1
end
end
This works perfectly fine except for one thing:
I have to define #instance_counter in each child class, or I will get an NoMethodError.
class Child < Entity
#instance_counter = 0
end
Is there a way to declare the variable in each child automatically so that I don't have to do it manually?

I don't know if this is the best way, but here is how I might do it:
class Entity
singleton_class.send(:attr_writer, :instance_counter)
def self.instance_counter; #instance_counter ||= 0; end
def initialize
self.class.instance_counter += 1
end
end

Related

Accessing a variable from a lower class that was NOT created as a child class (ie: using the "<" operator) in Ruby

I have a ToDo list program I'm writing for practice. My problem is that by separating concerns and making each list be a class while each task is also a class, I would like to be able to call the name of the list which the new task is being added to without having to pass the list name into the task class (either upon creation or later):
class HigherClass
def initialize
#higher_class_variable = unique_value
#instance_of_lower_class #keep variable empty for now
end
end
class LowerClass
def intitialize
#lower_class_variable = unique_value #this should be the same unique value as above
end
end
instance_of_higher_class = HigherClass.new
instance_of_higher_class.#instance_of_lower_class = LowerClass.new
instance_of_higher_class.#instance_of_lower_class.#lower_class_variable
#this should return the unique_value from the HigherClass instance
If you want to access attributes:
attr_reader :lower_class_variable
Then you can just do this:
#instance_of_lower_class.lower_class_variable
Same principle applies here for higher class:
class HigherClass
attr_writer :instance_of_lower_class
end
Then:
instance_of_higher_class.instance_of_lower_class = LowerClass.new
That all seems rather clunky considering you can do this:
class HigherClass
attr_accessor :unique
def initialize
#unique = unique_value
end
end
class LowerClass < HigherClass
def initialize
# Call superclass initialization
super
# Anything else you want here.
end
def something_using_unique
call_method(unique)
end
end

access an instance method of a class from another module's instance method

I have a class which declares a number of instance methods
class User < Group
def get_name
end
def show_profile
end
def get_task(task_id)
#some logic
end
end
And I want to call some of these methods from within a module. I can do it with Include statement.
include Users brings in all of the methods from User class. In this case I only want get_task and explicitly do not want get_name, show_profile etc..
I have a Tasks module which also has set of methods and one of those methods calls get_task method of User class.
module Tasks
class Project
def design
tid = 12
design_task = get_task(tid)
end
end
end
How this can be achieved without including other unnecessary methods of that class. Please help.
If the get_task method isn't depending on the user, you can use a class method like below. If it is depending on the user, you will have to get the server before you can run the method.
class User < Group
def get_name
end
def show_profile
end
def self.get_task(task_id)
#some logic
end
end
class Project
def design
tid = 12
design_task = User.get_task(tid)
end
end

Module Mixin Instance Tracker

I have the following piece of code, which tracks how many instances there are of a class:
module InstanceTracker
def self.instances
counter = 0
ObjectSpace.each_object do |i|
if i.class == self
counter += 1
end
end
return counter
end
end
What I want the end user to be able to do is:
class Foo
include InstanceTracker
end
But when I do that, I get a NoMethodError for Foo.instances. It works fine if I make InstanceTracker a class and do this:
class Foo < InstanceTracker; end
How can I make it a module mixin?
I played a little with your code. Apparently, you were comparing an instance's class with the caller, not the caller's class.
Try this:
module InstanceTracker
def instances
counter = 0
ObjectSpace.each_object do |i|
if i.class == self.class
counter += 1
end
end
return counter
end
end
Worked for me.
Also, note that the self in def self.instances will cause your code to fail. For instance method declaration, use the method's simple name.
BTW, your code will cause the interpreter to iterate over every single object and test each one of them with each method call.
I suggest you hack the class' new method so it increments a class variable, making this variable accessible through an attribute reader.

Accessing model methods from outside without creating an object

I have the following method:
class Store < ActiveRecord::Base
def my_func(str)
puts str
end
end
I can't seem to call it from outside the class like this:
Store::my_func("hi")
Any idea why?
What you have defined is an instance method. Basically this means you can only call it on instances of that class.
store = Store.new
store.my_func("hi")
If you want a class method, you need to define it a little differently. Either:
class Store < ActiveRecord::Base
def self.my_func(str)
puts str
end
end
Or (more useful if you're defining a lot of class methods):
class Store < ActiveRecord::Base
class << self
def my_func(str)
puts str
end
end
end
The above two work because classes are also instances of the class Class, so the implicit receiver self in the above two examples is that instance (the class itself).
You call a class method like this:
Store.my_func("hi")

How can I write derived Ruby classes that call a base class's method when they're defined?

Let's say I have this class:
class ComponentLibrary
def self.register(klass); ...; end
end
And suppose I also have this base class:
class BaseComponent
ComponentLibrary.register self
end
How can I write derivative classes, with a minimum of repetition, that will register themselves with ComponentLibrary when they're defined? (In other words, I'd prefer not to keep writing ComponentLibrary.register self everywhere.)
Just to be clear, I'm talking about writing other classes like:
class RedComponent < BaseComponent
# ...
end
class BlueComponent < BaseComponent
# ...
end
but I don't want to write ComponentLibrary.register self for each one.
class BaseComponent
def self.inherited(base)
ComponentLibrary.register(base)
end
end
class RedComponent < BaseComponent
end
Something along these lines might work for you.
Edit: changed to #inherited.

Resources