'Rails view_context
I cannot get my head around the view_context. I am currently implementing datatable in my app, taking references from this video.
What I didn't understand is how to access the content of the view_context, that is passed to the datatable class.
def index
respond_to do |format|
format.html
format.json { render json: UsersDatatable.new(view_context) }
end
end
then I accessed it in my datatable class
def initialize(view)
@view = view
end
I am using a gem called subscribem. I declare a Subscribem::Account and it pass around a variable current_account to every views. And in the datatable class I can access it like this
def initialize(view)
@view = view
@current_account = @view.current_account
end
but the problem is when in the controller, I add some variables like
def index
@date = DateTime.now #or date=DateTime.now
respond_to do |format|
format.html
format.json { render json: UsersDatatable.new(view_context) }
end
end
I cannot grab the passed date or @date.
def initialize(view)
@view = view
@current_account = @view.current_account
@date = @view.date
end
Solution 1:[1]
The key to understanding the view context is really to look at how a templating engine like ERB works (they all work pretty much the same on the high level).
You take a string (or buffer) and a context which is the data that you're inserting into the view as well as all the methods you could possibly want to use.
Take this trivial example:
require 'erb'
class Person
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def get_binding
binding
end
end
template = "Hello my name is <%= @first_name %> <%= @last_name %>"
person = Person.new('John', 'Doe')
erb = ERB.new(template)
puts ERB.new(template).run(person.get_binding) # Hello my name is John Doe
Since we are running the template engine with the binding from inside the instance of Person we can access its instance variables. It essentially works the same way as the view context. This "magic" is how the instance variables of your controller are available in the view and in helpers and why beginners end up confusing them with globals.
However in other contexts such as decorators or serializers encapsulation still applies. That @date = DateTime.now is still an instance variable of the controller and if you want to access it you either need to use instance_variable_get to violate encapsulation:
def initialize(view)
@view = view
@current_account = @view.current_account
@date = @view.instance_variable_get(:'@date')
end
Declare an accessor:
class UsersController
attr_reader :date
def index
@date = DateTime.now #or date=DateTime.now
respond_to do |format|
format.html
format.json { render json: UsersDatatable.new(view_context) }
end
end
end
class UsersDatatable
def initialize(view)
@view = view
@current_account = @view.current_account
@date = @view.date
end
end
Or change the interface of your class so that it does not need to poke inside of another object.
class UsersDatatable
def initialize(view, date: nil)
@view = view
@current_account = @view.current_account
@date = date
end
end
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | max |
