Initializing Instance Variable as an Array - Ruby

Initializing Instance Variable as an Array - Ruby

You are overriding ActiveRecord's initialize method. Try using super:

def initialize(*args, &block)
  super
  @name1 = []
end

How to Initialize Class Arrays in Ruby

You need to use initialize as a constructor as below code and is there any reason why not to use initialize/constructor. And please fix a typo error in class definition Class Something to class Something no camel case or first letter capitalize while in class

class Something 
def initialize
@something = Array.new
end
def dosomething
s = 5
@something << s
end
end

class variable @@ are available to the whole class scope. so they are working in the code and if you want to use instance variable @ you need to initialize it as above. The instance variable is share with instance/objects of a class

for more details visit the link Ruby initialize method

Instance variable initialization in Ruby

What you are doing is defining an instance variable on the class level (Since classes are instances of the Class class, this works just fine).

And no, there is no way around initialize.

Edit: You have a little misconception in your edit. attr_accessor doesn't add an instance variable to the class. What it does, literally, is this (using your example of my):

def my; @my; end
def my=(value); @my = value; end

It doesn't actively create/initialize any instance variable, it just defines two methods. And you could very well write your own class method that does similar things, by using define_method.

Edit 2:

To further illustrate how one would write such a method:

class Module
def array_attr_accessor(name)
define_method(name) do
if instance_variable_defined?("@#{name}")
instance_variable_get("@#{name}")
else
instance_variable_set("@#{name}", [])
end
end

define_method("#{name}=") do |val|
instance_variable_set("@#{name}", val)
end
end
end

class Test
array_attr_accessor :my
end

t = Test.new
t.my # => []
t.my = [1,2,3]
t.my # => [1, 2, 3]

How to initialise an instance variable dynamically in ruby?

Mocking @sites data:

@sites = [OpenStruct.new(
site_1_location: 'Japan',
site_2_location: 'India',
site_3_location: 'Chile',
site_4_location: 'Singapore'
)]

You can use instance_variable_set to set the instance variable

@sites.each do |site|
1.upto(4) do |i|
instance_variable_set("@var#{i}", site.send("site_#{i}_location"))
end
end

Now you can access the variables:

@var1 # returns "Japan"
@var2 # returns "India"
@var3 # returns "Chile"
@var4 # returns "Singapore"

How can I initialize instance variable?

If you want to persist anything between requests you need to store it somewhere:

  • Database
  • Memory based storage (Redis, Memcached)
  • File system

You can also pass state back and forth between the client and server without actually storing it with:

  • HTTP cookies
  • Query string parameters

Using a class variable is not really going to solve anything. It will only hold the variable as long as the class is held in memory. Every time the class is reloaded it will be reset.

Multi-threading is another huge issue here as Rails servers are commonly multi-threaded and class variables are not thread safe.

Declaring an instance variable outside of `initialize` method

I have been taught to declare my instance variables with def initialize

Since initialize is the first instance method call in an object's life cycle, you typically declare your instance variables right there in order to ensure properly initialized variables. It's also the first place I'd expect instance variables to be defined when reading code.

I have been under the impression that I could declare instance variables only within my initialize methods.

There's no such restriction. You can declare instance variable anywhere within your instance.

A common use is memoization:

class FooBar
def foo
@foo ||= expensive_operation
end
end

On the first call, this would evaluate expensive_operation and assign the result to @foo. On subsequent calls, @foo is returned.

Another popular example is Rails which uses instance variables to pass data from the controller to its view:

class FooController < ApplicationController
def index
@foos = Foo.all
end
end

is there a best practices rule I should follow, regarding where to declare instance variables

It depends on their purpose (see above examples). As a general rule, declare them in a way that avoids undefined variables (nil errors) and structure your code so it is easy to read / follow.

Ruby - automatically initialize class instance variables of child classes without inheriting the value

You don't have to initialize the class variable when it is being inherited. The Ruby style is to return and assign default value when the variable has not been set and is being accessed for the first time.

Just create another class method for that:

class AbstractClass
def self.metadata
@metadata ||= []
end

def self.add_metadata(metadata)
self.metadata << metadata
end
end

class ChildClass1 < AbstractClass
add_metadata(:child_class1)
end

class ChildClass2 < AbstractClass
add_metadata(:child_class2)
end

AbstractClass.metadata # => []
ChildClass1.metadata # => [:child_class1]
ChildClass2.metadata # => [:child_class2]

Initializing class instance variables in Ruby

Short answer: instance variables don't get inherited by subclasses

Longer answer: the problem is that you wrote @bar = [] in the body of the class (outside any method). When you set an instance variable, it is stored on whatever is currently self. When you're in a class body, self is the class object Foo. So, in your example, @foo gets defined on the class object Foo.

Later, when you try to look up an instance variable, Ruby looks in whatever is currently self. When you call add_bar from Baz, self is Baz. Also self is STILL Baz in the body of add_bar (even though that method is in Foo). So, Ruby looks for @bar in Baz and can't find it (because you defined it in Foo).

Here's an example that might make this clearer

class Foo
@bar = "I'm defined on the class object Foo. self is #{self}"

def self.get_bar
puts "In the class method. self is #{self}"
@bar
end

def get_bar
puts "In the instance method. self is #{self} (can't see @bar!)"
@bar
end
end

>> Foo.get_bar
In the class method. self is Foo
=> "I'm defined on the class object Foo. self is Foo"

>> Foo.new.get_bar
In the instance method. self is #<Foo:0x1056eaea0> (can't see @bar!)
=> nil

This is admittedly a bit confusing, and a common stumbling point for people new to Ruby, so don't feel bad. This concept finally clicked for me when I read the 'Metaprogramming' chapter in Programming Ruby (aka "The Pickaxe").

How I'd solve your problem: Look at Rails' class_attribute method. It allows for the sort of thing you're trying to do (defining an attribute on a parent class that can get inherited (and overidden) in its subclasses).



Related Topics



Leave a reply



Submit