1

I have an instance variable that I set in a controller.

@cost=[1,2,3]

Eventually a view gets called that calls a partial that in turn calls a helper in app/helpers.

In the debugger I can see that @cost is still [1,2,3] when I enter that helper method.

Inside the helper method, I set @cost to [4,5,6] and then call a helper method set_cost that is defined in application_controller.rb.

class ApplicationController < ActionController::Base
  helper_method :set_cost
  def set_cost
    @cost=[7,8,9]
  end
end

When I enter set_cost, I can see in the debugger that @cost has reverted to [1,2,3].

When I return back to the helper method in app/helpers, I can see in the debugger that @cost is no longer [7,8,9], but has reverted to [4,5,6].

If I call set_cost directly from the controller, @cost is [7,8,9] when control returns back to the controller.

Is there a way that I can access and manipulate the instance variable across the controller, view, partial, helper method in app/helpers, and helper method in application_controller.rb such that the reference / values stay consistent? It's as though it's changing the scope and making local versions of the variable.

I realize there may be design and practical benefits to passing @cost to set_cost (my actual function is more complex than what I showed), updating it, and then returning it to the original function for assignment there, but even if that accomplishes what I want, I'd like to understand the Rails design better. I thought an instance variable was akin to a global variable, but apparently not.

Thank you for your help.

1 Answer 1

1

An instance variable is not a global variable - it is tied to a particular instance (hence the name).

Rails allows you to access controller instance variables from a view. This works by copying the controller instance variables: the view_assigns methods in AbstractController::Rendering creates a hash of all the instance variables. Later on, the view object uses that hash to recreate the instance variables. When you say that it's as if there are local copies of the variable being made, that's pretty much exactly what is happening.

The values are shared, i.e. initially in both the view and the controller @cost.object_id will be the same. If your helper were to do something like @cost.replace(...) then you would see that change everywhere, however when you reassign @cost that assignment does not affect the controller (and vice-versa - the copy of controller instance variables to the view is a once-off operation).

"Normal" helpers end up being instance methods of the view context, however ones created by helper_method are controller instance methods - rails basically defines a view helper that looks like

def set_cost
  controller.set_cost
end

You can probably dodge these issues by mutating @cost rather than reassigning it, but I find the idea that a view helper might mutate state like this surprising.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, @frederick-cheung, for your fast and insightful reply. I'm sorry that because my reputation is < 15, my up vote doesn't change the publicly recorded post score.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.