0
votes

I have some helpers that are defined on runtime that are specific for a single call, e.g. a single instance of a controller (the next call could have different helper methods). Is there a robust way to add a helper method to an instance of a controller and it's view only, without adding the helper to other instances and views of this controller?

To define a helper for ALL instances, you could use the .helper_method method, e.g.

class Article < ApplicationController
  helper_method :my_helper

  def my_helper
    # do something
  end
end

I digged around in the source code, and found the (fairly private looking) #_helpers method which returns a module that contains all helpers for this instance. I could now use some meta programming to define my methods on this module

def index
  _helpers.define_singleton_method(:my_helper) do
    # do something
  end
end

But I don't like this approach because I'm using a clearly private intended method that could easily change in the future (see the leading _).

If I only needed the helper inside the controller instance only, I could just call #define_singleton_method on the instance directly, but this doesn't make it available to the view.

So I'm looking for an official "Rails way" to define a helper for a single instance of a controller and it's view, like Rails provides with it's class method .helper_method.

1
Why do you want to add a helper to a single instance of a controller?mrzasa
It's for our internal tooling, developers can define views in a database and assign variables to it. One action of the controller renders this views and needs to define the helpers dynamically on a per record base23tux
I'd suggest to move the logic to a dynamic decorator object, but TBH I can't say for suremrzasa

1 Answers

0
votes

I'm not sure if there is an official Rails way of doing this.

You could create an anonymous module and extend from that. Since this solution uses pure Ruby, you'll have to extend both the controller and view.

before_action :set_helpers, only: :index

def index
  # ...
end

private

def set_helpers
  @helpers = Module.new do |mod|
    define_method(:my_helper) do
      # do something
    end
  end

  extend(@helpers)
end
<% extend(@helpers) %>