Ошибка ActiveRecord с пространствами имен или ожидаемое поведение? - PullRequest
1 голос
/ 24 апреля 2020

Рельсы 4.1.16

Ruby 2.2.7

У меня есть эта модель ActiveRecord:

class Something::Type < ActiveRecord::Base

При ссылке на такую ​​модель:

Something::Type.find_by_whatever("test")

Я получаю следующую ошибку:

NoMethodError: undefined method `find_by_whatever' for ActiveRecord::AttributeMethods::Serialization::Type:Class

Я понимаю, что константы Ruby разбиты, так что Type существует как собственная константа, и автозагрузчик находит ActiveRecord::AttributeMethods::Serialization::Type first.

Однако обращение к пространству имен «абсолютным» способом (с префиксом двоеточия) должно решить проблему, но результат тот же. Есть идеи почему?

::Something::Type.find_by_whatever("test")

NoMethodError: undefined method `find_by_whatever' for ActiveRecord::AttributeMethods::Serialization::Type:Class

1 Ответ

2 голосов
/ 24 апреля 2020

Проблема при определении класса с помощью оператора результата видимости заключается в том, что вложение модуля разрешается до точки определения (точки, в которой вы используете ключевое слово модуля). Если вы посмотрите на вложение модуля:

class Something::Type < ActiveRecord::Base
  puts Module.nesting.inpsect # [Something::Type]
end

Класс, даже не вложенный в модуль Something. Что даст вам чрезвычайно удивительный константный поиск:

module Something
  FOO = "test"
end

class Something::Type
  puts Foo # gives a uninitialized constant error since its not looking in the Something module
end

Вместо этого вы ВСЕГДА должны объявлять классы пространства имен с явным вложением:

module Something
  class Type
    puts Module.nesting.inspect # [Something::Type, Something]
    puts Foo  # test
  end
end

Что дает модулю вложение [Something::Type, Something], что означает, что он будет правильно искать константы в том же пространстве имен Something.

Это то, что старый автозагрузчик classi c склонялся к тому, чтобы замаскировать, поскольку он полагался на патч обезьян Module#const_missing. Zeitwork не так делает это правильно.

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