2017kamb
2017kamb

Reputation: 242

different way to create object specific methods in ruby

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?

Upvotes: 1

Views: 174

Answers (4)

Cary Swoveland
Cary Swoveland

Reputation: 110755

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.

Upvotes: 2

steenslag
steenslag

Reputation: 80105

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.

Upvotes: 1

2017kamb
2017kamb

Reputation: 242

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>)

Upvotes: 0

ray
ray

Reputation: 5552

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

Upvotes: 1

Related Questions