Calling instance methods from Class methods in ruby - ruby-on-rails

Is this the right way of calling an Instance method from a class method? Here the instance_var is passed with the Name object. I want to invoke func1 from the instance_var object passed to the class method.
I wrote this :
Class Name
def initialize
#name
end
def func1(value)
puts value
end
def self.func2(instance_var,val)
instance_var.func1(val)
end
end

How do you call func2?
Your code has a small error. You wrote Class instead class. With Class you get a syntax error.
This code works:
class Name
def func1(value)
puts value
end
def self.func2(instance_var,val)
instance_var.func1(val)
end
end
x = Name.new
Name.func2(x, 12) #12
#or
Name.func2(Name.new, 12) #12
Your
def initialize
#name
end
will create an empty variable #name. It will never get a value. To assign a value you need:
class Name
def initialize (var)
#name = var
end
end
x = Name.new(:x)

Related

How to access class method from instance method in ruby on rails non activerecord model

I have a non activerecord rails model:
class Document
attr_accessor :a, :b
include ActiveModel::Model
def find(id)
initialize_parameters(id)
end
def save
...
end
def update
...
end
private
def initialize_parameters(id)
#a = 1
#b = 2
end
end
In order to find the Document, I can use:
Document.new.find(3)
So, to get it directly I changed the find method to
def self.find(id)
initialize_parameters(id)
end
And I get the following error when I run
Document.find(3)
undefined method `initialize_parameters' for Document:Class
How can I make this work?
You can't access an instance method from a class method that way, to do it you should instantiate the class you're working in (self) and access that method, like:
def self.find(id)
self.new.initialize_parameters(id)
end
But as you're defining initialize_parameters as a private method, then the way to access to it is by using send, to reach that method and pass the id argument:
def self.find(id)
self.new.send(:initialize_parameters, id)
end
private
def initialize_parameters(id)
#a = 1
#b = 2
end
Or just by updating initialize_parameters as a class method, and removing the private keyword, that wouldn't be needed anymore.
This:
class Document
attr_accessor :a, :b
def self.find(id)
initialize_parameters(id)
end
end
Is not trying to "access class method from instance method" as your title states. It is trying to access a (non-existent) class method from a class method.
Everything Sebastian said is spot on.
However, I guess I would ask: 'What are you really trying to do?' Why do you have initialize_parameters when ruby already gives you initialize that you can override to your heart's content? IMO, it should look something more like:
class Document
attr_accessor :a, :b, :id
class << self
def find(id)
new(id).find
end
end
def initialize(id)
#a = 1
#b = 2
#id = id
end
def find
# if you want you can:
call_a_private_method
end
private
def call_a_private_method
puts id
end
end

how to call define_method in rails after_kind hook

when i call define_method in hook function :
error occurred:
undefined method `define_method' for #<Myentity:0x007f9e4eda5928>
here is an example:
class EntityInstance < ApplicationRecord
after_find :define_relation
def define_relation
define_method "example" do |x|
end
end
end
How to change the context in hook method or how to use this function in hook method?
thx a lot!
define_method should be called in the context of the class.
Meaning, depending on where you want to define the method (either in singleton class of the instance of Myentity or in Myentity class) you should be using either
def define_relation
# define method available only to this particular instance of Myentity
class_eval do
define_method "example" do |x|
end
end
end
or
def define_relation
# define a method available to all instances of Myentity class
self.class_eval do
define_method "example" do |x|
end
end
end

How to access accessor's instance variable from a subclass?

How to access attr_accessor's instance variable from a subclass?
class A
attr_accessor :somevar
#somevar = 123
puts #somevar
end
class B < A
def meth
puts #somevar
end
end
B.new.meth
puts nil...
P.S. I can use ActiveSupport.
You need to set the instance variable in an initialize method -- this gets called whenever a new class instance is created:
class A
attr_accessor :somevar
def initialize
#somevar = 123
end
end
First, you do not have a instance of A to assign a value. Put an initialize method on A so while creating an instance of B, you can pass somevar value as a parameter to the new function:
class A
attr_accessor :somevar
def initialize(somevar)
#somevar = somevar
end
end
class B < A
def meth
puts #somevar
end
end
B.new('LOL').meth

Instantiating a class in Ruby and populating instance variable

I have a feeling I'm missing something very simple here. I have a class that is linked to an external service. I want to instantiate it by either calling a create method or a find method. Both methods will populate an instance variable "#node" with a hash, either by creating a node or finding it.
I have
class GenreInfluence
##neo ||= Neography::Rest.new()
attr_accessor :node
def initialize
end
def self.create
#node = ##neo.create_node
self.new
end
def self.find(node_id)
#node = ##neo.get_node(node_id)
self.new
end
def get_hash
#node
end
If I comment out what's going on, I can see it's creating the class and getting the correct hash back however:
theInstance = GenreInfluence.find(20)
theInstance.get_hash
Just returns nil. Why is the hash not being stored in the instance variable!?
You can't set instance variables in a non-instance (static, or class) method. Furthermore, both your methods are returning self.new, which effectively returns a new instance of the class with no instance variables set.
How about the following, that creates a new instance of the class in the static class methods, sets the variable on that instance, and then returns it (instead of returning self.new):
class GenreInfluence
##neo ||= Neography::Rest.new()
attr_accessor :node
def initialize
end
def self.create
influence = self.new
influence.node = ##neo.create_node
influence
end
def self.find(node_id)
influence = self.new
influence.node = ##neo.get_node(node_id)
influence
end
def get_hash
#node
end
end
You are returning self.new from your find method. That's a new instance of GenreInfluence with a fresh set of instance variables.
How about
class GenreInfluence
##neo ||= Neography::Rest.new()
attr_accessor :node
def initialize(node_id = nil)
if (node_id.nil?) then
#node = ##neo.create_node
else
#node = ##neo.get_node(node_id)
end
end
def find(node_id)
#node = ##neo.get_node(node_id)
end
def get_hash
#node
end
end
and then
theInstance = GenreInfluence.new()
theInstance.get_hash
theInstance1 = GenreInfluence.new(20)
theInstance1.get_hash
theInstance2 = GenreInfluence.new()
theInstance2.get_hash
theInstance2.find(20)
theInstance2.get_hash

how to set an instance variable from a class method?

I am trying to do a custom active record macro. But it right now seems impossible set an instance variable from within it's block.. here is what i am trying to do.
module ActiveRecord
class Base
def self.included(base)
base.class.send(:define_method, :my_macro) do |args|
# instance_variable_set for the model instance that has called this
# macro using args
end
end
end
end
i have tried class_eval, instance_eval.. but nothing seems to work or i don't how to use them.
Thanks in advance.
Edit: Let me try to explain better. I have a class method. An instance of the class calls this method. Now, this class method should instruct the instance to set an instance variable for itself.
Edit- this is how i want o use the macro
class MyModel < ActiveRecord::Base
my_macro(*args)
def after_initialize
# use the value set in the macro as #instance variable
end
end
Is this what you are thinking of:
class DynamicAdd
def add_method
self.class_eval do
attr_accessor :some_method
end
end
end
You can then do the following:
k = DynamicAdd.new
k.some_method = "hi"
should result in an undefined method error.
But,
k = DynamicAdd.new
k.add_method
k.some_method = "hi"
should work.
You can use this same format to define other types of methods besides attr_accessors as well:
class DynamicAdd
def add_method
self.class_eval do
def some_method
return "hi"
end
end
end
end
Hm.. Isn't included() a Module method? I don't think you can use that in a class like you have written. If you want to create a class method you can do
class Base
def self.my_method
end
or
class Base
class << self
def my_method
end
end
If all you want to do is to add an instance variable to an existing object, then you can use #instance_variable_set
class Base
class << self
def my_method(instance_of_base, value)
instance_of_base.instance_variable_set "#x", value
end
end
end
a = Base.new
a.class.send(:my_method, *[a,4])

Resources