Search code examples
ruby-on-railsrubyproc

Ruby define method to return proc which makes use of an argument


In Ruby, I'd like to define a method that takes an argument, which returns a proc full of methods that make use of that argument. Something like the following

def test(word)
  proc do
    def hello
      puts word
    end
  end
end

my_proc = test('hello')
my_proc.call.hello

When running this code, the local variable 'word' is undefined

To give some more context, I am trying to make use of association extensions, which allow you to provide a block of methods to an association to define extra helper methods on the association. I have some methods I'd like to use on several similar active record models with similar associations, but they only differ by a certain symbol when making calls (the name of the join table passed to through on a has_many relationship). So ideally I was thinking of making a method that accepts that symbol, which could then be used in the implementation of the association extension.


Solution

  • Your example has two problems:

    1. You can't call a "proc full of methods" like that -- it'll work as an association extension, but there the block is evaluated as a module body, not called.

    2. The def keyword resets the local variable scope. To get a value into a function, you can either define it using define_method instead (that block retains surrounding scope), or put the value somewhere else the function will be able to find it (a class variable, for example).


    def test(word)
      proc do
        define_method(:hello) do
          puts word
        end
      end
    end
    
    Class.new(&test("hello")).new.hello
    

    Separately, if you're defining approximately the same method on several associations, there might be a simpler path by defining them as class-level scopes.