Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a private method xxx using self.xxx() from within another private method resulting in error "private method `xxx' called"

Tags:

private

ruby

I'm trying to get a good Ruby coding style. To prevent accidently calling a local variable with the same name, I'm always using self. where appropriate. But now I stumbled over this:

class MyClass < ActiveRecord::Base
  before_validation :sanitize_user_data

  private

  def sanitize_user_data
    self.sanitize_name # with ".self" it's a problem, without it's not!
  end

  def sanitize_name
    unless self.name.nil?
      self.name.gsub!(/\s+/, ' ')
      self.name.strip!
    end
  end
end

The above code results in an error

private method sanitize_name called

but when removing self. and just using sanitize_name, it works. Why's that?

like image 633
Joshua Muheim Avatar asked Aug 12 '12 16:08

Joshua Muheim


2 Answers

This happens because private methods cannot be called with an explicit receiver, and saying self.sanitize_name is explicitly specifying the object (self) that should receive sanitize_name, rather than relying on the implicit receiver (which is also self).

You can't avoid this, you either need to call plain old sanitize_name without an explicit receiver, or do self.send(:sanitize_name). I'm not sure that always explicitly specifying self is really "good style", but that's subjective. If you want to ensure you're calling a method instead of a variable, add parenthesis:

def a; "method"; end
a = "variable"
a() #=> "method"
a   #=> "variable"
like image 194
Andrew Marshall Avatar answered Nov 15 '22 06:11

Andrew Marshall


Why's that?

By definition. Private methods can only be invoked by a receiverless message send, that's the definition of what private means.

like image 24
Jörg W Mittag Avatar answered Nov 15 '22 05:11

Jörg W Mittag