Как переменные экземпляра Rails передаются в представления?

В моем приложении Rails у меня есть такой контроллер:

class MyController < ApplicationController
  def show
    @blog_post = BlogPost.find params[:id]
  end
end

На мой взгляд, я могу просто сделать это:

<%= @blog_post.title %>

Мне неловко с магией. Как это достигается?

Ответ 1

Когда визуализируется представление, переменные экземпляра и их значения выбираются из контроллера и передаются в инициализатор представления, который устанавливает их в экземпляр представления. Это делается с использованием этих рубиновых методов:

instance_variables - получает имена переменных экземпляра (документация) instance_variable_get(variable_name) - получает значение переменной экземпляра (документация) instance_variable_set(variable_name, variable_value) - устанавливает значение переменной экземпляра (документация)

Вот код Rails:

Сбор переменных экземпляра контроллера (github):

def view_assigns
  hash = {}
  variables  = instance_variables
  variables -= protected_instance_variables
  variables -= DEFAULT_PROTECTED_INSTANCE_VARIABLES
  variables.each { |name| hash[name[1..-1]] = instance_variable_get(name) }
  hash
end

Передача их в представление (github):

def view_context
  view_context_class.new(view_renderer, view_assigns, self)
end

Установка их в виде (github):

def assign(new_assigns) # :nodoc:
  @_assigns = new_assigns.each { |key, value| instance_variable_set("@#{key}", value) }
end

Ответ 2

decent_exposure gem является альтернативой действию переменной экземпляра контроллера Rails. В readme есть хорошая запись об этой проблеме.