Установка атрибута из модели без использования self не работает - PullRequest
4 голосов
/ 20 марта 2011

Модель устройства имеет следующие атрибуты: имя, версия и полное имя

Полное имя - имя + версия:

class Device < ActiveRecord::Base
  def prepare
    full_name = (!show_version || version.nil?)? name : name + " " + version.to_s
  end
end

Когда я делаю следующее:

d = Device.new :name => "iPhone", :version => "4"
d.prepare
d.full_name # get nil

Я получаю ноль за атрибут "полное имя"

Когда я использую «self», это работает:

class Device < ActiveRecord::Base
  def prepare
    self.full_name = (!show_version || version.nil?)? name : name + " " + version.to_s
  end
end

При выполнении «prepare» я получаю «iPhone 4» для атрибута «full_name».

Некоторые люди здесь говорили мне, что это хороший способ избегать использования «я» внутри методов класса. Но это приносит неприятности.

Вопрос в том, почему это не работает без использования «я»?

Ответы [ 3 ]

13 голосов
/ 20 марта 2011

Когда вы используете сеттеры, вам нужно использовать self, потому что в противном случае Ruby будет интерпретировать его как определяемую новую локальную переменную full_name.

Для получателей нам не нужно вызывать self, потому что Ruby сначала ищет локальную переменную full_name, а когда у него нет локальной переменной full_name, он ищет метод full_name и получает добытчик. Если у вас определена локальная переменная full_name, она вернет значение локальной переменной.

Это лучше объясняется в предыдущем вопросе

13 голосов
/ 20 марта 2011

В этих случаях вы должны использовать себя, я не думаю, что это проблема. Если вы используете self, то интерпретатор будет знать, что вы ссылаетесь на атрибут объекта. Если вы не используете self, это означает, что это просто локальная переменная, которая не сохраняется нигде после завершения метода. Это нормальное поведение. Вы также можете использовать self[:full_name]= ... в качестве метода установки, но в этом случае это не имеет значения.

Обновление

@ AntonAL

Поскольку методы-получатели распознаются без self..

Когда вы пытаетесь использовать атрибут name, интерпретатор будет искать локальную переменную в текущем методе. Если не находит, то ищет атрибут экземпляра. Пример:

def your_method
  self.name = 'iPhone'
  puts name
  #iPhone
  name = 'iPod'
  puts name
  #iPod
  puts self.name
  #iPhone
end

И iPhone будут храниться в атрибуте name экземпляра вашего объекта. И iPod будет потеряно после завершения метода.

0 голосов
/ 06 ноября 2018

Это ожидается, потому что так работает ActiveRecord. Если вам нужно установить произвольные атрибуты, вам придется использовать объекты другого типа.

Например, Ruby предоставляет библиотеку под названием

OpenStruct

, что позволяет создавать объекты, которым вы можете назначить произвольный ключ и значения. Если вы хотите получить значение из атрибута без self, он даст вам экземпляр класса OpenStruct с атрибутом экземпляра глобальной переменной. Но если вы хотите установить новый атрибут, он создаст новый экземпляр класса OpenStruct с новыми атрибутами. Без self у вас будут старые объекты OpenStruct, которые не имеют атрибутов и приведут к ошибке.

Возможно, вы захотите использовать такую ​​библиотеку, а затем преобразовать объект в соответствующий экземпляр ActiveRecord, только когда вам нужно сохранить в базе данных.

Не пытайтесь моделировать ActiveRecord, чтобы он вел себя так, как вы только что описали, потому что он просто не был разработан, чтобы вести себя таким образом

...