2014-06-24 2 views
2

Вот как моя структура данных выглядитПочему возникает ошибка «неинициализированная константа» при ссылке на класс?

Controller 
    API 
     V1 
     Controller1.rb 
     Controller2.rb 
     Serializers 
      Model1Serializer.rb 
      Model2Serializer.rb 

Я пытаюсь получить доступ к сериализаторам в моих контроллерах

Вот мой контроллер

class API::V1::Controller1 < ApplicationController 

    require_relative 'model1_serializer' 

    def doStuff 
     render json:MyData, each_serializer:Model1Serializer 
    end 

end 

Вот мой сериализатору

class API::V1::Serializers::Model1Serializer < ActiveModel::Serializer 
    # Code here for serializing 
end 

Я получаю следующее сообщение об ошибке. Почему он думает, что Model1Serializer находится под контроллером 1?

неинициализированным постоянной API :: V1 :: Controller1 :: Model1Serializer

Если в моем контроллере я изменить Model1Serializer к API::V1::Serializers::Model1Serializer то он работает, за исключением того, я не хочу быть зависимым от V1 в моем пространстве имен, в этом случае. Если я решит переместить код на V2, я не перестаю менять код, чтобы указать на V2. Каков наилучший способ справиться с этим?

ответ

1

Ваш контроллер API::V1::Controller1, но ваш серийный номер API::V1::Serializers::Model1Serializer.

В вашем методе doStuff вы пытаетесь найти Model1Serializer - но нет способа увидеть этот класс из этой точки пространства имен.

Попробуйте использовать API::V1::Serializers::Model1Serializer вместо этого.


Update: ОП отредактировал свой вопрос:

Если в моем контроллере я изменить Model1Serializer к API :: V1 :: сериализаторы :: Model1Serializer затем он работает, за исключением того, я не хочу быть зависимым от Vq в пространстве имен y, таким образом, если я решит переместить код на V2, я не перестаю изменять код, чтобы указать на V2. Каков наилучший способ справиться с этим?

Быстрый способ определить Current = V1 в модуле API, а затем ссылаться на API::Current::... при ссылках на свои модели из контроллеров.

Лучше всего подумать о том, почему вам необходимо одновременно предоставить несколько API-интерфейсов в одном и том же приложении, и это действительно правильный способ его версии. (Это, вероятно, выходит за рамки одного SO ответа, хотя, и будет слишком сильно зависит от конкретного приложения.)

+0

Я обновил свой вопрос, я скорее не имею никакой зависимости от V1, каких-либо предложений? Не хочу, чтобы вернуться и обновить мой код, чтобы указать на V2, когда я создаю новую версию – aryaxt

2

«Почему думать Model1Serializer находится под контроллером 1:

Строго говоря что это на самом деле не так. при поиске постоянная, Ruby проверяет несколько пространств имен (если они имеются), но сообщение об ошибке упоминается только сокровенные один.

Почему я получаю ошибку «неинициализированная константы» при ссылке на класс?

Чтобы ответить на это, важно понять, как Ruby ищет постоянные. Если у вас есть эта иерархия пространства имен:

module API 
    module V1 
    class Controller1 
    end 
    end 
end 

Если вы обращаетесь к Model1Serializer из Controller1 рубин проверяет следующие вложенные пространства имен:

  1. API::VI::Controller1::Model1Serializer
  2. API::VI::Model1Serializer
  3. API::Model1Serializer
  4. ::Model1Serializer

Но Model1Serializer определено в API::VI::Serializers::Model1Serializer, которое не входит в этот список. Вот почему Ruby не может его найти.

Чтобы исправить это, вы должны изменить ошибочную строку, чтобы включить суб-модуль:

render json: MyData, each_serializer: Serializers::Model1Serializer 

Но скорее всего, это еще не будет работать, потому что вы используете «контекстные пространства имен», т.е. API::V1 вместо module API; module V1; ...; end; end Это не позволяет Ruby искать родительские пространства имен, потому что они не добавляются в список вложенных модулей.

Другими словами, только следующие пространства имен проверяются Ruby:

  1. API::VI::Controller1::Serializers::Model1Serializer
  2. ::Serializers::Model1Serializer

Вы можете получить доступ к иерархии модулей, вызвав Module.nesting в нужном месте кода.

Отказ от ответственности: В Ruby постоянный поиск намного больше, чем представлено здесь.

Смежные вопросы