Какая разница между использованием self.attribute и атрибутом в модели?

В Ruby on Rails, какая разница между использованием self.attribute и атрибута в модели?

В этом примере предположим, что my_attr является атрибутом пользователя, который хранится в базе данных.

class User < ActiveRecord::Base
  def do_something!
    self.my_attr = 123
  end

  def do_another_thing!
    my_attr = 456
  end
end

Ответ 1

Разница в том, что одна работает, а другая - нет или, по крайней мере, не так, как вы ее намереваетесь.

Ваша вторая версия ничего не делает. Это не эквивалентно вызову self.my_attr = 123, вместо этого он просто создает локальную переменную с именем my_attr и устанавливает ее на 123, а затем выкидывает ее при возврате метода. Это никак не влияет на значение модели my_attr.

class User < ActiveRecord::Base
  def do_another_thing!
    my_attr = 456

    puts self.my_attr # nil (or whatever value it was before)
  end
end

И наоборот, если вы хотите получить доступ к методу, определенному на объекте, вы можете (и should) пропустить self:

class User
  def name=(value)
    @name = value
  end

  def name
    @name
  end

  def age=(value)
    @age = value
  end

  def age
    @age
  end

  def do_something
    self.name = "bob" # self is required
    puts name # bob

    age = 47 # @age is unaffected
    age # nil
  end
end

Обратите внимание, что это не вопрос Rails, это вопрос Ruby. Здесь нет кода, специфичного для Rails, это поведение является частью работы синтаксиса Ruby.

Ответ 2

общее правило заключается в том, что всякий раз, когда вы модифицируете "я", присваивая значение некоторому атрибуту, используйте "я" явно

self.first_name = 'Prasad' #if self isnt used, it will create a local variable.

и если вы ссылаетесь на этот атрибут (но не изменяете), не используйте 'self'

def name
  name.camelize
end

---- UPDATE -----

всякий раз, когда мы обращаемся к любому атрибуту, ruby ​​проверяет, определены ли методы getter (reader) и setter (writer) для этого атрибута.

Итак, в приведенном выше случае (когда вы назначаете значение атрибуту), вы не имеете прямого доступа к атрибуту, а передаете значение сеттеру, который будет внутренне присваивать значение атрибуту.

2.1.0p0 :008 > User.first.first_name
=> "Prasad" 
2.1.0p0 :009 > (User.first.methods - Object.methods).include? :first_name
=> true 
2.1.0p0 :010 > (User.first.methods - Object.methods).include? :first_name=
=> true 

Вы можете попробовать, добавив метод в любую модель

def some_name
  first_name = 'Some name'
  puts self.first_name
  self.first_name = 'Random Username'
  puts self.first_name
end

и перезагрузите консоль и выполните

2.1.0p0 :017 > User.first.some_name
Prasad
Random Username
=> nil 

Ответ 3

do_something! является методом экземпляра. Итак, здесь self является экземпляром User, my_attr = - ваш метод экземпляра пользователя. Функция назначает значение переменной экземпляра пользователя @may_attr.

В "do_another_thing!" my_attr может быть только что объявленной переменной.

Ответ 4

В этом случае нет никакой разницы. Но предположим, что у вас есть локальная переменная в определении метода:

def do_something!
  self.my_attr = 123
end

def do_another_thing!(my_attr)
  puts "my_attr is #{my_attr}"
  puts "self.my_attr is #{self.my_attr}"
end

do_something!          
do_another_thing!(456)

Тогда выход будет

my_attr is 456
self.my_attr is 123 

self представляет объект. Когда вы вызываете метод на self, вы вызываете метод специально для этого объекта.

Ответ 5

Ключевое слово self в Ruby дает вам доступ к текущему объекту - объекту, который получает текущее сообщение.

So self.attribute относится к current object attribute, где просто attribute существует с его scope.

Прочтите это руководство self для получения более подробной информации.