PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, August 24, 2022

[FIXED] How to call any instance method in ruby object without instantiating it?

 August 24, 2022     activesupport, class, initialization, module, ruby     No comments   

Issue

I am creating a helper module to initialize the object before calling its methods

module Initialized
  extend ActiveSupport::Concern

  class_methods do
    def run(*args)
      new(*args).run
    end

    def call(*args)
      new(*args).call
    end

    def execute(*args)
      new(*args).create
    end
  end
end

So instead of defining run, call, and execute in my helper module I need to receive any method name and check if it exists on the main class after initializing it, then call the requested instance method if exists in the main class or raise an error if not

I would say my targeted code would be something like this

module Initialized
  extend ActiveSupport::Concern
  class_methods do
    def _(*args, methodname)
      new(*args).try(:send, "#{methodname}") || raise 'Method not exist'
    end
  end
end

Sample usage would be

class MyClass
  include Initialized

  def initialize(param1)
    @param1 = param1
  end

  def call
    puts "call '#{@param1}'"
  end
end

then calling

MyClass.call('method param')

I found these links but couldn't find my answer yet:

meta-dynamic-generic-programming-in-ruby

ruby-module-that-delegates-methods-to-an-object

template-methods-in-ruby


Solution

Despite the fact method_missing would do the job, I'd probably avoid it in this case in favor of a more explicit delegation. Simple and dirty example:

module InstanceDelegator
  def delegate_to_instance(*methods)
    methods.each do |method_name|
      define_singleton_method method_name do |*args|
        new(*args).public_send(method_name)
      end
    end
  end
end

class Foo
  extend InstanceDelegator

  delegate_to_instance :bar # <- define explicitly which instance methods
                            # should be mirrored by the class ones

  def bar
    puts "bar is called"
  end

  def baz
    puts "baz is called"
  end
end

# and then

Foo.bar #  => bar is called
Foo.baz # NoMethodError ...

# reopening works too
class Foo
  delegate_to_instance :baz
end

Foo.baz # baz is called

Pros:

  1. you don't need to redefine method_missing (less magic -> less pain when you debug the code)
  2. you control precisely which instance methods to be wrapped with the class level "shorthand" (fewer chances to delegate something you don't want to - more robust code)
  3. (minor) no need to raise NoMethodError explicitly - you can fully rely on the core dispatching as it is...


Answered By - Konstantin Strukov
Answer Checked By - David Goodson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing