Rails ActiveSupport::Concern и оценка методов

У меня есть это приложение, которое использует Devise с помощником current_user. Когда я создаю модуль, current_user становится nil после того, как я упоминаю об авторстве, хотя этого никогда не происходит.

class PagesController < ApplicationController
  include ModuleTest

  def index
    a_test_method
  end
end

И ModuleTest:

module ModuleTest
  extend ActiveSupport::Concern

  def a_test_method
    puts "(BEFORE)===========> #{current_user.inspect}"
    current_user = nil if false
    puts "(AFTER) ===========> #{current_user.inspect}"
  end
 end

Выход:

(BEFORE)===========> #<User id: 1>
(AFTER) ===========> nil

Однако если я удалю/закомментирую эту строку # current_user = nil if false, current_user останется в силе:

(BEFORE)===========> #<User id: 1>
(AFTER) ===========> #<User id: 1>

Будет ли это как-то связано с ленивой оценкой?

ИЗМЕНИТЬ

Вся проблема зависит от того, как Ruby определяет переменные, когда оператор не оценивается:

2.3.4 (main):0 > defined? this_never_seen_variable_before
=> nil
2.3.4 (main):0 > this_never_seen_variable_before = "value" if false
=> nil
2.3.4 (main):0 > defined? this_never_seen_variable_before
=> "local-variable"
2.3.4 (main):0 >
2.3.4 (main):0 > this_never_seen_variable_before_2
   NameError: undefined local variable or method `this_never_seen_variable_before_2' for main:Object
from (pry):119:in `<main>'
2.3.4 (main):0 > this_never_seen_variable_before_2 = "value" if false
=> nil
2.3.4 (main):0 > this_never_seen_variable_before_2
=> nil
2.3.4 (main):0 >

Как это работает снизу?


person Bruno Velasco    schedule 01.12.2017    source источник


Ответы (1)


  1. current_user — это вспомогательный метод, предоставляемый Devise, а не локальная переменная.

  2. Нет такого вспомогательного метода с именем current_user=. Вы можете доказать это, изменив current_user = nil на self.current_user = nil и увидев, как он падает. Но это не имеет отношения к вашему вопросу.

Итак, в результате вы определили локальную переменную current_user между двумя puts, которая затеняет вспомогательный метод с тем же именем.

Странно то, что хотя current_user = nil не выполняется из-за if false, локальная переменная все еще определяется, и ее значение неявно устанавливается равным nil. Вот почему ваш второй puts показывает nil. Даже если вы измените свой current_user = nil на current_user = :someone, ваш второй puts все равно должен показывать nil.

person Aetherus    schedule 01.12.2017