Actually i am new to the oops concepts in ruby, here i want to call the instance variables from one function to another function in same class.but im getting undefined method for second function "one_object"
module User
class Object
class << self
def add_object(items)
@data={}
@data.merge!(items)
end
# i want to use above @data = {} for next one_object method after adding items to the add_object method
def one_object
@data.merge!({"ext"=>"1.0"})
end
end
end
end
a = User::Object.add_object({"txt"=>"text_file","csv"=>"csv_file"})
p a.one_object
Expected Output:
{"txt"=>"text_file", "csv"=>"csv_file", "ext"=>"1.0"}
CodePudding user response:
You assign the result of add_object
to a
(i.e. your a
is now a Hash), but next you are going to call one_object
on a
(but one_object
is part of User::Object
and not of your Hash instance).
If you add to add_object
another line, containing self
, you will receive your expected output.
With the change, add_object
will return User::Object
, and you won't run into your initial issue.
CodePudding user response:
In Ruby, Object
is the root class of all objects. Although you can have your own Object
class within User
, it could cause a lot of confusion.
Let's simplify your problem my removing the User
module (it's not relevant to the example) and by renaming Object
to Foo
(you'll find a better name). To initialize instance variables you can use the initialize
method which is invoked by default every time you construct an object via new
:
class Foo
def initialize
@data = {}
end
end
foo = Foo.new
#=> #<Foo:0x00007fb551823d78 @data={}>
# ^^^^^^^^
That hash you assign to @data
will be shared among all instance methods. In addition, each Foo
instance will have its own @data
hash. To merge!
another hash into it, you can use:
class Foo
def initialize
@data = {}
end
def add(hash)
@data.merge!(hash)
end
end
foo = Foo.new
#=> #<Foo:0x00007fbc80048230 @data={}>
foo.add({"abc"=>123})
#=> {"abc"=>123}
foo.add({"def"=>456})
#=> {"def"=>456}
foo
#=> #<Foo:0x00007fbc80048230 @data={"abc"=>123, "def"=>456}>
In order to chain multiple add
calls (a so-called fluent interface), you have to return self
from within the method:
class Foo
def initialize
@data = {}
end
def add(hash)
@data.merge!(hash)
self # <- like this
end
end
foo = Foo.new
#=> #<Foo:0x00007ff7408003d8 @data={}>
foo.add({"abc"=>123}).add({"def"=>456})
#=> #<Foo:0x00007ff7408003d8 @data={"abc"=>123, "def"=>456}>
Finally, to add static data, you could simply call your own method:
class Foo
def initialize
@data = {}
end
def add(hash)
@data.merge!(hash)
self
end
def add_more
add({"more" => 789})
end
end
foo = Foo.new
#=> #<Foo:0x00007f99b20f8590 @data={}>
foo.add({"abc"=>123}).add({"def"=>456}).add_more
#=> #<Foo:0x00007f99b20f8590 @data={"abc"=>123, "def"=>456, "more"=>789}>