Какая разница между использованием 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 для получения более подробной информации.