1

I am aware of just one way to create instance specific methods in ruby i.e.

 class Test;end
 obj1 = Test.new
 class << obj1
   def greet
     p 'Welcome'
   end
 end
 obj1.greet #    "Welcome"
 obj2 = Test.new
 obj2.greet # through error as,
 Traceback (most recent call last):
 NoMethodError (undefined method `greet' for #Test:0x0000564fb35acef0>)

or

 class Test;end
 class << (obj1 = Test.new)
   def greet
     p 'Welcome'
   end
 end
 obj1.greet #    "Welcome"
 obj2 = Test.new
 obj2.greet # through error as,
 Traceback (most recent call last):
 NoMethodError (undefined method `greet' for #Test:0x0000564fb35acef0>)

Here I have two questions:

  1. What is the real world use of such kind of object specific methods?
  2. What are other different ways to create object specific methods in Ruby?
2
  • Yes, (1) could have broad use but please provide me at least few. Commented Feb 11, 2019 at 7:14
  • 3
    (1) a common real-world and everyday use are "class methods". These are defined on the class object rather than its class (the Class class) in order to limit their scope to that specific object. Commented Feb 11, 2019 at 9:09

4 Answers 4

2
class Test
end

obj = Test.new

Here are some ways to create the hash, other than

class << obj
  def greet
    ...
  end
end

and (as mentioned in another answer)

def obj.greet
  ...
end

#1

obj.singleton_class.class_eval do
  def greet1
    'Welcome'
  end
end

obj.greet1 #=> "Welcome"

#2

obj.singleton_class.class_eval "def greet2
  'Get lost'
end"

obj.greet2 #=> "Get lost" 

This form can be useful when creating singleton methods dynamically.

#3

obj.singleton_class.instance_eval do
  define_method(:greet3) { 'yo' }
end

obj.greet3 #=> "yo"

#4

obj.singleton_class.
    public_send(:define_method, :greet4) { 'yo-yo' }

obj.greet4 #=> "yo-yo"

#5

obj.define_singleton_method(:greet5) { 'yo who?' }

obj.greet5 #=> "ho who?"

#6

module M
  def greet6
    'hi ya'
  end
end

obj.extend M

obj.greet6 #=> "hi ya"

#7

module M
  def greet7
    'hi you'
  end
end

obj.singleton_class.include M

obj.greet7 #=> "hi you"

obj.methods(false)
  #=> [:greet3, :greet4, :greet1, :greet2, :greet5] 
obj.methods.grep /greet/
  #=> [:greet3, :greet4, :greet1, :greet2, :greet5,
  #    :greet6, :greet7] 

The practical use of creating singleton methods is obvious for modules (including classes), but calls for an opinion as it concerns other objects.

Sign up to request clarification or add additional context in comments.

2 Comments

Or simply def obj.greet ; 'hi' ; end
@Stefan, I didn't include that because it was covered in another answer. In fact I wrote the edit shown above but evidently didn't save it.
1

You have defined class block as class << obj1 for only obj1 object which is object specific. So greet method is only defined for obj1 object and not for other objects of same class.

Better you inspect in following pattern

class Test
  attr_accessor :name

  def initialize(name)
    self.name = name
  end
end

obj1 = Test.new('test1')

class << obj1
  def greet
    puts self.inspect, self.object_id, self.name
    puts 'Welcome'
  end
end

obj1.greet
obj2 = Test.new
obj2.greet

In above, obj1 & obj2 both have different object ids.

1. What is the real world use of such kind of object specific methods?

It is good practice to know various pattern to define methods. This is useful when you want to define methods dynamically or when you load classes but want to define methods based on columns of model table present in database. Module#define_method is one of the best for such uses, cancancan is one of the gem who define helper methods dynamically in initializer.

2. What are other different ways to create object specific methods in Ruby?

  1. define_singleton_method
  2. class_eval

3 Comments

There is Object#define_singleton_method for this magic, no need to use define_method.
@halfelf Yes, define_singleton_method will define singleton method for object but I am giving way to define instance methods to any class so any instance can access that method. Correct if I miss something
@halfelf OP is interested in defining object specific method so I will edit answer to add this point
1

An example of a use case: suppose you have production code which uses a hash as data structure. As time progresses, it appears that a class would have been a better choice, because smarter behaviour than just holding data is required - for instance data should be validated. This validation code is only meaningful in the context of this specific hash. You could define a method validate_username in the public namespace or some module, but def the_hash.validate_username;#code;end would arguably be a better solution.

Comments

0

As per @mu_is_too_short comment, another way is,

class Test; end
obj1 = Test.new

def obj1.pancakes
  p 'Where is pancakes house?'
end

obj1.pancakes # "Where is pancakes house?"
obj2 = Test.new
obj2.pancakes
Traceback (most recent call last) :
NoMethodError
(undefined method `pancakes' for #<Test:0x0000564fb35ca310>)

Comments

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.