Метод, относящийся к извлеченному в упакованном методе, выходит за пределы области видимости при помещении внутрь метода объектов

#ruby #scope

#ruby #класс #переменные #методы #область видимости

Вопрос:

Когда я помещаю метод, который ссылается на pulled in package внутри другого метода, он покидает область видимости и завершается сбоем.

Каков правильный способ сделать это. Я пытался играть с «self», но я новичок, и это не сработало.

Желаемое решение. Не работает. Возвращает ошибку.

неопределенный метод `учитывает» значение nil:NilClass (NoMethodError)

 require 'package that has 'accounts''


class Name

    @sandbox = #working API connection

    def get_account
        @sandbox.accounts do |resp|         #This is where error is
          resp.each do |account|

            if account.name == "John"
                name = account.name
            end

          end
        end
    end


end


new = Name.new
p new.get_account
  

Это работает, но не создает повторно используемый метод.

 require 'package that has 'accounts''

class Name

    @sandbox = #working API connection


        @sandbox.accounts do |resp|       
          resp.each do |account|    
            if account.name == "John"
                p account.name
            end
          end
        end




end


new = Name.new
  

Комментарии:

1.Вам нужно self.class.instance_variable_get(:@sandbox).accounts.. . То есть вам нужно значение переменной экземпляра класса @sandbox , поэтому сначала вам нужно изменить область видимости на class: self.class . (Это один из случаев, когда self. требуется, потому что без этого Ruby будет думать class , что это ключевое слово.) Затем, поскольку у класса нет геттера для @sandbox , вам нужно использовать метод Object#instance_variable_get .

2. самый сложный в мире $this->

Ответ №1:

  1. Ошибка в коде заключается в том, что @sandbox является атрибутом класса. Значение будет инициализироваться при создании объекта класса. Запись инициализации в классе не будет иметь никакого эффекта. @Maxim объяснил это в своем ответе.

  2. Для второго кода, когда интерпретатор выполняет код, он выполняет его один раз. Но этот код не может выполняться более одного раза.

Код должен быть,

 require 'package that has 'accounts''


class Name

    def initialize
      @sandbox = #working API connection
    end

    def get_account
        @sandbox.accounts do |resp|         #This is where error is
          resp.each do |account|

            if account.name == "John"
                name = account.name
            end

          end
        end
    end


end


new = Name.new
p new.get_account
  

Комментарии:

1. Значение @sandbox одинаково для всех экземпляров, так что разве не имеет смысла, чтобы оно было переменной экземпляра класса?

2. Конечно! Если область @sandbox находится на уровне класса, то @@sandbox должен выполнить трюк в коде. Я не уверен в намерениях проекта в этом случае. С переменными класса могут возникнуть некоторые проблемы с расширяемостью позже, если они решат изменить API для определенных классов.

3. Я предлагаю, чтобы это @sandbox была переменная экземпляра класса, а не переменная класса. (кстати, многие Rubiests, включая меня, никогда не используют переменные класса.)

4. О, извините, я запутался. Я также добавил @sandbox только в качестве переменной экземпляра. Я неправильно истолковал комментарий и подумал, что предложение состоит в том, чтобы использовать его в качестве переменной класса. Я думаю, что мы здесь на одной странице. Я что-то недопонимаю?

Ответ №2:

Чтобы понять это, вам нужно понять концепцию одноэлементных классов в Ruby.

Имя класса является самим объектом и @sandbox является переменной экземпляра этого объекта.

Если вы пишете def self.get_account , вы могли бы использовать @sandox там, но тогда этот метод недоступен для экземпляров Name , например, вы должны вызывать Name.get_account и нет Name.new.get_account . На самом деле, это добавляет метод к одноэлементному классу Name , и именно поэтому вы можете получить доступ к @sandbox там.

Чтобы создать переменную экземпляра, которая могла бы использоваться в экземплярах Name , вы должны сделать это в initialize методе Name .