rails has_many и доступ внутри класса - PullRequest
2 голосов
/ 23 июня 2009

У меня есть модель рельсов класса

class Model <  ActiveRecord::Base

  has_many :object_collection


  def add_object(object)
      object_collection.push object // works
      @object_collection.push object // does not work
      self.object_collection.push object // works
  end
end

Мне было интересно, если кто-нибудь может объяснить мне, почему @ не работает, но сам я думал, что эти два означают одно и то же

ура

Ответы [ 3 ]

4 голосов
/ 23 июня 2009

Они не одинаковы. Рассмотрим следующий код Ruby:

class Person
  attr_accessor :employer
end
john = Person.new
john.employer = "ACME"
john.employer # equals "ACME"

Метод attr_accessor удобно генерирует для вас средство чтения и записи атрибутов (employer= и employer). Вы можете использовать эти методы для чтения и записи атрибута, который хранится в переменной экземпляра @employer.

Теперь мы можем переписать вышеприведенное к следующему, что функционально идентично приведенному выше коду:

class Person
  def employer=(new_employer)
    @works_for = new_employer
  end
  def employer
    @works_for
  end
end
john = Person.new
john.employer = "ACME"
john.employer # equals "ACME"

Теперь переменная экземпляра @employer больше не используется. Мы решили написать методы доступа вручную, и у нас есть свобода выбора другого имени для переменной экземпляра. В этом конкретном примере имя переменной экземпляра отличается от имени атрибутов доступа. Ничто не мешает вам сделать это.

Это похоже на то, как ActiveRecord хранит свои атрибуты внутри. Они не хранятся в переменных экземпляра с одинаковыми именами, поэтому ваш push вызов @object_collection не работает.

Как вы понимаете, читатели и писатели атрибутов предлагают определенную абстракцию, которая может скрыть от вас детали реализации. Поэтому чтение и запись переменных экземпляра непосредственно в подклассы обычно считается плохой практикой.

1 голос
/ 23 июня 2009

Они не означают одно и то же. Одна - это переменная экземпляра, другая - метод.

@foo означает «значение переменной экземпляра foo», где как self.foo означает «значение вызова метода foo для себя».

Обычно для метода foo = устанавливается переменная экземпляра @foo, поэтому я вижу, как кто-то новичок в этом языке может быть сбит с толку. Я бы посоветовал вам взять книгу на рубиновом языке. Есть один специально для людей, которые сделали несколько рельсов, но никогда не изучали рубин. Вы часто можете взломать рельсы, не понимая язык или значение этих утверждений, но вы будете гораздо менее продуктивны, чем тот, кто тратит небольшое количество времени на изучение самого языка рубина.

Как правило, всегда используйте форму self.foo, поскольку она менее чувствительна к изменениям в определении классов.

1 голос
/ 23 июня 2009

@ foo определяет переменную экземпляра с именем @foo. foo идентифицировал метод, названный foo. По умолчанию переменные экземпляра в Ruby являются закрытыми. Это означает, что вы не можете получить доступ к значению переменной экземпляра, если у вас нет публичного метода, который выставляет значение.

Эти методы называются сеттерами и геттерами. По договоренности setter и getter имеют одно и то же имя переменной экземпляра, но это не является обязательным требованием.

class MyClass

  def initialize
    @foo
  end

  def foo=(value)
    @foo = foo
  end
  def foo
    @foo
  end

  def an_other_foo=(value)
    @foo = foo
  end
  def an_other_foo
    @foo
  end

end

Хотя методы и переменные экземпляра могут иметь одинаковые имена, они являются разными элементами. Если вам не понятна эта тема, вам, вероятно, нужно прекратить играть с Rails и вернуться к изучению работы Ruby.

В вашем конкретном случае object_collection не существует как переменная экземпляра, потому что это метод ассоциации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...