0

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"}
5
  • 2
    If you’re new to OOP, you maybe should start by defining a casual class with some instance methods rather than jumping straight into the class << self rabbit hole ;-) Commented Dec 29, 2021 at 14:17
  • yeah thanks for suggestion , can you please share some knowledge on this , i mean can you provide solution to this. Commented Dec 29, 2021 at 14:42
  • @Bharath why did you add class << self in the snippet above first of all? It is doing some "magic" you better should not touch until you are comfortable with some basics (it's not magic at all, but it does require a bit deeper understanding of Ruby object model). Create a simple class that does the necessary job, then move further if necessary... Commented Dec 29, 2021 at 15:00
  • @KonstantinStrukov now i updated my code . so im trying to use module with class , can you provide solution.the thing is here im getting the answer for "add_object" method but also i need final output using next method Commented Dec 29, 2021 at 15:24
  • 1
    Object is an existing class, maybe you can come up with another name for your class. Commented Dec 29, 2021 at 15:40

2 Answers 2

2

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 by 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}>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for sharing knowledge, for one question you unlocked my few answers
2

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.

1 Comment

Also: while it wasn't part of your question, I highly assume you want the first line of add_object to read @data||={}. The way as it's written currently in your question, you would not add objects (as the method name would suggest), but instead replace the data every time you call the method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.