неопределенный метод класса в Ruby (вызывается перед определением метода)

В итоге получил очень странную ошибку:

Когда я запускаю этот код:

class HomeFeature
    include Mongoid::Document
    include Mongoid::Timestamps
    include Mongoid::Bitfield

    belongs_to :home

    def self.amenities
        %w(lobby jacuzzi sauna cinema games roof_garden events_room tennis_court visits_space roaster green_areas cistern)
    end

    bitfield :amenities, *HomeFeature.amenities.map(&:to_sym)
end

Он отлично работает, но это:

class HomeFeature
    include Mongoid::Document
    include Mongoid::Timestamps
    include Mongoid::Bitfield

    belongs_to :home

    bitfield :amenities, *HomeFeature.amenities.map(&:to_sym)

    def self.amenities
        %w(lobby jacuzzi sauna cinema games roof_garden events_room tennis_court visits_space roaster green_areas cistern)
    end
end

Выдает ошибку: ```NoMethodError: неопределенный метод `удобства' для HomeFeature:Class````

Может кто-нибудь объяснить, почему это происходит? Большое спасибо


person javierojeda    schedule 30.03.2017    source источник
comment
Ответ на самом деле уже находится в заголовке вашего вопроса.   -  person Jörg W Mittag    schedule 31.03.2017
comment
Да, но почему? Это не то, как должен работать Ruby, не так ли? Это не похоже на С   -  person javierojeda    schedule 31.03.2017
comment
Нет, это не похоже на C, но это не значит, что порядок не имеет значения. Подумайте об этом так: когда вы определяете класс, интерпретатор Ruby читает класс, строка за строкой, оценивая код в контексте класса. Когда он сталкивается с определением метода, он определяет метод, но на самом деле ничего не запускает. Порядок имеет значение.   -  person Glyoko    schedule 31.03.2017
comment
Причина, по которой это обычно не проблема с методами экземпляра, где вы можете написать метод экземпляра, который вызывает другой метод экземпляра, определенный где-то ниже в классе, заключается в том, что эти методы обычно не вызываются в то же время, когда они определяются. Когда вы пишете такие методы экземпляра, интерпретатор читает класс, строка за строкой, запуская методы класса и определяя новые методы. Затем, только когда весь класс определен, объекты создаются из класса. На данный момент методы уже определены, и методы могут нормально вызывать друг друга.   -  person Glyoko    schedule 31.03.2017


Ответы (1)


Во втором примере вы пытаетесь вызвать метод класса amenities до того, как он был определен (он вызывается в строке *HomeFeature.amenities.map(&:to_sym), но определяется только позже). Здесь важен порядок исходного кода, так как код анализируется сверху вниз.

person gwcodes    schedule 30.03.2017