How to access accessor's instance variable from a subclass? - ruby-on-rails

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

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

Ruby method and variable inheritance

I'm trying to access variables defined in class One, through inheritance, in class Two. I can't seem to find the right way of going about it - it seems to work for methods:
class One
class << self
def test
puts "I'm a method from class one"
end
end
end
end
And as a new object the variable is accessible:
class Two < One
test
end
#=> I'm a method from class one
class Test
attr_accessor :a
def initialize
#a = "hi"
end
end
Test.new.a
#=> "hi"
But I'm trying to do something like:
class One
class << self
a = "hi"
end
end
class Two < One
a
end
#=> NameError: undefined local variable or method `a' for Two:Class
For now I'm using class variables, but I'm sure there's a better way:
class One
##a = "hi"
end
class Two < One
##a
end
#=> "hi"
local and class instance variables wouldn't be accessible through inheritance in Ruby.
Limosine is an example of a class inheriting, a variable (brand) and a method, to_s
class Car
def initialize(brand)
#brand = brand
end
def to_s
"(##brand, ##model)"
end
end
class Limosine < Car
def initialize(brand, model)
super(brand)
#model = model
end
end
Use:
puts Merc.new("Mercedes", "Maybach")to_s

Calling instance methods from Class methods in ruby

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)

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