What does `& method (: method_ name)` mean in ruby?

I tried to create a class with a private class method. I want this private class method to be available for use inside the instance method.

The following was my first attempt:

class Animal
  class << self
    def public_class_greeter(name)
      private_class_greeter(name)
    end

  private
    def private_class_greeter(name)
      puts "#{name} greets private class method"
    end
  end

  def public_instance_greeter(name)
    self.class.private_class_greeter(name)
  end
end

Animal.public_class_greeter('John')working fine, print John greets private class method.

However, Animal.new.public_instance_greeter("John")an error: NoMethodError: private method 'private_class_greeter' called for Animal:Class.

It is expected that the call self.class.private_class_greeterwill be the same as Animal.private_class_greeterthat, clearly causing an error.

After finding how to fix this, I came up with the following code that does the job:

class Animal
  class << self
    def public_class_greeter(name)
      private_class_greeter(name)
    end

  private
    def private_class_greeter(name)
      puts "#{name} greets private class method"
    end
  end

  define_method :public_instance_greeter, &method(:private_class_greeter)
end

I do not quite understand what is happening here: &method(:private_class_greeter).

Could you explain what this means?

If I had to replace:

define_method :public_instance_greeter, &method(:private_class_greeter)

with:

def public_instance_greeter
  XYZ
end

then what should be the content instead XYZ?

+4
2

Ruby &method(:private_class_greeter)?

&method(:private_class_greeter)

  • method(:private_class_greeter)
  • &.

method?

method method , . irb:

def foo
  "bar"
end

my_method = method(:foo)
#=> #<Method: Object#foo>

, :

my_method.call
#=> "bar"

my_method.source_location   # gives you the file and line the method was defined on
#=> ["(irb)", 5]

# etc.

& ?

& a Proc , , . to_proc , , , Proc, Proc.

method to_procProc. method & :

def call_block
  yield
end

call_block &my_method   # same as `call_block &my_method.to_proc`
#=> "bar"

define_method , . &method(:private_class_greeter) private_class_greeter .


&:symbol

. Symbol to_proc, :

["foo", "bar"].map(&:upcase)
#=> ["FOO", "BAR"]

# this is equivalent to:
["foo", "bar"].map { |item| item.upcase }

# because
:upcase.to_proc

# returns this proc:
Proc { |val| val.send(:upcase) }

&method(:private_class_greeter)?

, :

define_method :public_instance_greeter do |name|
  self.class.send(:private_class_greeter, name)
end

, define_method, , :

def public_instance_greeter(name)
  self.class.send(:private_class_greeter, name)
end
+8

-, . private 2 : , public_instance_greeter .

, Kernel#send:

class Animal
  class << self
    def public_class_greeter(name)
      private_class_greeter(name)
    end

    private
    def private_class_greeter(name)
      puts "#{name} greets private class method"
    end
  end

  def public_instance_greeter(name)
    self.class.send(:private_class_greeter, name)
  end
end

Animal.public_class_greeter('John')
# John greets private class method
Animal.new.public_instance_greeter("John")
# John greets private class method
+3

Source: https://habr.com/ru/post/1681115/


All Articles