Переменные экземпляра в ActiveSupport::Concern

Я читал, что модули (в данном случае ActiveSupport::Concern) в ruby ​​являются общими для всех инициализированных экземпляров класса. Поэтому, если бы это было правдой, это означало бы, что любые переменные экземпляра будут общими для всех экземпляров в памяти.

module SetPassword
  extend ActiveSupport::Concern
  attr_reader :password
  def password=(new_password)
    @password = new_password
    self.crypted_password = password_digest(new_password, salt)
  end
end

class User
  include SetPassword
end

u = User.new; u.password = 'abcdef'
u2 = User.new; u2.password = '123456'

Безопасен ли приведенный выше код? Или второй пользователь переопределит первого пользователя?


person jdfolino    schedule 27.02.2019    source источник
comment
Поэтому, если бы это было правдой, это означало бы, что любые переменные экземпляра будут общими для всех экземпляров в памяти. Это неправильно. Попробуйте и посмотрите.   -  person jvillian    schedule 27.02.2019
comment
Также обратите внимание, что в вашем примере есть опечатка, последняя строка должна читаться как u2.password = '123456' (а не u.password = '123456'.)   -  person Aleksei Matiushkin    schedule 27.02.2019


Ответы (1)


Module#include скрыто вызывает Module#append_features. Это означает, что ничего не используется совместно, и это может быть легко проверено (ActiveSupport::Concern не имеет ничего общего с кодом, который вы должны проверить).

module SetPassword
  attr_reader :password
  def password=(new_password)
    @password = new_password
    puts <<~EOS
    Setting password to: #{@password} (id: #{@password.__id__}).
    Object: #{self.class.name} (#{self.__id__}).
    Method: #{__callee__} on #{self.method(__callee__).__id__}.
    EOS
  end 
end

class User
  include SetPassword
end

u1 = User.new; u1.password = 'abcdef'
u2 = User.new; u2.password = '123456'

Приведенный выше код демонстрирует, что все (сам пароль, переменная экземпляра и даже метод сам по себе) отличается:

▶ u1 = User.new; u1.password = 'abcdef'
#⇒ Setting password to: abcdef (id: 46968741459360).
#  Object: User (46968741459420).
#  Method: password= on 46968741459040.

▶ u2 = User.new; u2.password = '123456'
#⇒ Setting password to: 123456 (id: 46968734231740).
#  Object: User (46968734232020).
#  Method: password= on 46968734230640.
person Aleksei Matiushkin    schedule 27.02.2019