Ruby : How to define a util class? - ruby

Can we define utility class with instance methods and then in another class, using object of the utility class, call the instance methods?
For example,
class Usertype # utility class
def add(a, b)
c = a + b
return c
end
end
class User
user = Usertype.new
def test
return user.add(1,2)
end
end
Can this be done?

Yup, you can achieve that by using modules:
module Usertype
def self.add(a,b)
a + b
end
end
class User
def test
Usertype.add 1, 2
end
end
u = User.new
u.test

I am not sure what you are asking but here is what you can do:
class Usertype
def add(a,b)
return a + b
end
end
class User
def test
u = Usertype.new
return u.add(1,2)
end
end
Or you can use an instance variable in user:
class User
def initialize
#u = Usertype.new
end
def test
return #u.add(1,2)
end
end

Related

Ruby - Access instance variables of called class

I have two classes Book::Utils, Table::Utils and I calling one class from the other which are not parent-child classes.
If I call class2 from class1 -> In class2, can we access already present class1 instance variables?
module Table
attr_accessor :account_id
class Utils
def initialize(params)
#account_id = params[:account_id]
end
def calculate
book = Book.new
final_account_id = book.get_account_id
return final_account_id
end
end
end
module Book
class Utils
def get_account_id
# Here I want to access Table's instance variables
# Like #account_id + 20
end
end
end
I am calling Table::Utils.new({account_id: 1}).calculate
Expected result : 21
Can we achieve this?
You need to pass instance of the class you need to call and then you can use accessors:
module Table
attr_accessor :account_id
class Utils
def initialize(params)
#account_id = params[:account_id]
end
def calculate
book = Book.new
final_account_id = book.get_account_id(self)
return final_account_id
end
end
end
module Book
class Utils
def get_account_id(table)
table.account_id + 20
end
end
end
or just pass the value that is needed
module Table
attr_accessor :account_id
class Utils
def initialize(params)
#account_id = params[:account_id]
end
def calculate
book = Book.new
final_account_id = book.get_account_id(account_id)
return final_account_id
end
end
end
module Book
class Utils
def get_account_id(other_id)
other_id + 20
end
end
end

Is it possible to access a method without creating an instance?

I have a class within a module and it has methods:
module D
class Dog
#name = 'pluto'
def setName( n )
#name = n
end
def getName ()
return #name
end
end
end
Can I access getName without creating an instance of Dog like the static method in C++? Something like:
D::Dog.getName ()
instead of:
d = D::Dog.new
d.getName()
I believe you're looking for what is known as a class method in Ruby:
module SomeModule
class SomeClass
#class_variable = "some_string" # An instance variable on a class
def self.some_class_method
#class_variable # Return can be omitted in Ruby
end
# This is how setter methods are usually written in Ruby
def self.some_class_method= new_value
#class_variable = new_value
end
end
end
SomeModule::SomeClass.some_class_method
#=> "some_string"

Ruby loop through instance methods and run them

I have the following class:
module StatCalculators
class Passing
def initialize(user_id, game_id)
#user_id = user_id
#game_id = game_id
end
def save_completion_percentage
completions = StatType.find_by_name("Completions").stats.where(athlete_id: #user_id).sum(:float_value)
attempts = StatType.find_by_name("Pass Attempts").stats.where(athlete_id: #user_id).sum(:float_value)
value = completions/attempts
stat = Stat.new(value: value, game_id: #game_id, athlete_id: #user_id, float_value: value)
stat.save(validate: false)
end
end
end
The class above has the potential to have a lot more methods that need to be run without having to call each method individually... is there a way to run all instance methods in the initialize method?
It is possible:
module StatCalculators
class Passing
def initialize(user_id, game_id)
#user_id = user_id
#game_id = game_id
klass = self.class
klass.instance_methods(false).each do |method|
klass.instance_method(method).bind(self).call
end
end
...
end
end

How to pass a method to instance_eval?

I want to call instance_eval on this class:
class A
attr_reader :att
end
passing this method b:
class B
def b(*args)
att
end
end
but this is happening:
a = A.new
bb = B.new
a.instance_eval(&bb.method(:b)) # NameError: undefined local variable or method `att' for #<B:0x007fb39ad0d568>
When b is a block it works, but b as a method isn't working. How can I make it work?
It's not clear exactly what you goal is. You can easily share methods between classes by defining them in a module and including the module in each class
module ABCommon
def a
'a'
end
end
class A
include ABCommon
end
Anything = Hash
class B < Anything
include ABCommon
def b(*args)
a
end
def run
puts b
end
end
This answer does not use a real method as asked, but I didn't need to return a Proc or change A. This is a DSL, def_b should have a meaningful name to the domain, like configure, and it is more likely to be defined in a module or base class.
class B
class << self
def def_b(&block)
(#b_blocks ||= []) << block
end
def run
return if #b_blocks.nil?
a = A.new
#b_blocks.each { |block| a.instance_eval(&block) }
end
end
def_b do
a
end
end
And it accepts multiple definitions. It could be made accept only a single definition like this:
class B
class << self
def def_b(&block)
raise "b defined twice!" unless #b_block.nil?
#b_block = block
end
def run
A.new.instance_eval(&#b_block) unless #b_block.nil?
end
end
def_b do
a
end
end

ruby: accessing caller variables from declared obj instance

class X
end
class A
def get_it
puts #the_variable
end
end
class B
def init_it
#the_variable = X.new
a = A.new
end
end
In the above code I want methods of Class A to access the instance of X instantiated in B
Try using Object#instance_variable_set:
class B
def init_it
#the_variable = X.new
a = A.new
a.instance_variable_set(:#the_variable, #the_variable)
end
end

Resources