2

In my Rails application I have a class that I want to initialize and then access it throughout my controllers. So the idea is that I set it via the application controller if it's not already been defined:

class ApplicationController < ActionController::Base

  before_action :set_custom_class

  # create an instance of customclass if doesn't exist
  def set_custom_class
    @custom_class ||= CustomClass.new
  end

end

An example of the class:

class CustomClass

  def initialize; end

  def custom_method
    @custom_method
  end

  def custom_method=(content)
    @custom_method = content
  end

end

If I then have a controller like:

class MyController < ApplicationController

  def method_1
    # set the custom_method value on my instance
    @custom_class.custom_method('Some content')
    # return the value I set above
    @variable = @custom_class.custom_method
    redirect_to :method_2
  end

  def method_2
    # I should be able to retrieve the same value from that same instance
    @variable = @custom_class.custom_method
  end

end

What I'm finding is that when calling method_1 the @variable will return my content fine, but when calling method_2 AFTER method_1 (so the custom_method for the app wide @custom_class has been set) it's returning nil.

Why isn't the instance being retained? The @custom_class shouldn't be creating a new instance as it's already been set. So I can't understand why the value I have set gets lost when requesting it.

Cameron
  • 27,963
  • 100
  • 281
  • 483
  • Can you check if `set_custom_class` is creating a new object every time or is it really caching? maybe the issue is there – amrdruid Jul 17 '18 at 19:58

3 Answers3

2

You witnessing such behaviour, because state of a controller is not preserved between requests. For example, imagine that current_user method sets @current_user for one request and returns the same user for another one.

Please, consider an option of using cookies or database for sharing state between requests.

Otherwise, a workaround would be setting a class variable of CustomClass, but I don't recommend to do it.

Igor Drozdov
  • 14,690
  • 5
  • 37
  • 53
  • Thanks for that. I was under the impression that once you created an instance in the application controller it would be retained but now that I think about it... why would it! The reason I asked was I was looking into using this Gem: https://github.com/zokioki/fitbit_api/blob/master/lib/fitbit_api/client.rb#L51 and this line is where the same issue happens in that when you create a client and get a token back you lose it the very next request making that method useless unless you keep sending a refresh token to a new instance. – Cameron Jul 17 '18 at 20:27
  • I've even raised a ticket for it: https://github.com/zokioki/fitbit_api/issues/4 as it seems that's a bit weird to have that method outside of using the refresh_token version of initializing the client. – Cameron Jul 17 '18 at 20:28
0

Looks like your before_action will re-instantiate the new object on every request. That means that since you aren't passing anything through to the class in Method2, it will come out as NULL.

Kao
  • 11
  • 2
-1

Since you said app-wide, why not make it app-wide?

In config/application.rb,

module App
  class Application < Rails::Application

    def custom_class
      @custom_class ||= CustomClass.new
    end 
  end 
end 

in your application code,

Rails.application.custom_class

Josh Brody
  • 5,153
  • 1
  • 14
  • 25