Разделить Grape API (не Rails) на разные файлы

Я пишу API в Grape, но он стоит отдельно, без Rails, Sinatra или чего-то еще. Я хотел бы разделить файл app.rb на отдельные файлы. Я просмотрел Как разделить вещи в винограде API?, но это с Rails.

Я не уверен, как заставить это работать с модулями или классами — я пробовал создавать подклассы разных файлов в моем большом GrapeApp, но это было уродливо, и я даже не уверен, что это работает правильно. Как лучше всего это сделать?

В настоящее время у меня есть версии, разделенные по папкам (v1, v2 и т. д.), но это все.


person tekknolagi    schedule 12.07.2013    source источник


Ответы (1)


Вам не нужно создавать подклассы из основного приложения, вы можете просто монтировать отдельные подклассы Grape::API внутри основного. И, конечно же, вы можете определить эти классы в отдельных файлах и использовать require для загрузки всех маршрутов, сущностей и помощников, которые могут понадобиться вашему приложению. Я нашел полезным создать одно мини-приложение для каждого «объекта домена» и загрузить их в app.rb, что выглядит следующим образом:

  # I put the big list of requires in another file . . 
  require 'base_requires'

  class MyApp < Grape::API
    prefix      'api'
    version     'v2'
    format      :json

    # Helpers are modules which can have their own files of course
    helpers APIAuthorisation

    # Each of these routes deals with a particular sort of API object
    group( :foo ) { mount APIRoutes::Foo }
    group( :bar ) { mount APIRoutes::Bar }
  end

Я размещаю файлы в папках довольно произвольно:

# Each file here defines a subclass of Grape::API
/routes/foo.rb 

# Each file here defines a subclass of Grape::Entity
/entities/foo.rb

# Files here marshal together functions from gems, the model and elsewhere for easy use
/helpers/authorise.rb

Я бы, вероятно, эмулировал Rails и имел бы папку /models/ или что-то подобное для хранения определений ActiveRecord или DataMapper, но, как оказалось, в моем текущем проекте она предоставляется в другом шаблоне.

Большинство моих маршрутов выглядят очень просто, они просто вызывают соответствующий вспомогательный метод, а затем представляют сущность на его основе. Например. /routes/foo.rb может выглядеть так:

module APIRoutes
  class Foo < Grape::API
    helpers APIFooHelpers

    get :all do
      present get_all_users_foos, :with => APIEntity::Foo
    end

    group "id/:id" do
      before do
        @foo = Model::Foo.first( :id => params[:id] )
        error_if_cannot_access! @foo
      end

      get do
        present @foo, :with => APIEntity::Foo, :type => :full
      end

      put do
        update_foo( @foo, params )
        present @foo, :with => APIEntity::Foo, :type => :full
      end

      delete do
        delete_foo @foo
        true
      end
    end # group "id/:id"
  end # class Foo
end # module APIRoutes
person Neil Slater    schedule 12.07.2013
comment
Каждый из этих routes файлов require винограден? - person tekknolagi; 17.07.2013
comment
@tekknolgi: Вы должны require 'grape' перед определением Grape::API подклассов, но это может быть в основном app.rb, если вы не хотите повторять это везде. - person Neil Slater; 17.07.2013
comment
Хорошо, и это не приведет к ошибке из-за неопределенных переменных, классов и прочего? - person tekknolagi; 17.07.2013
comment
@tekknolgi: Не должно, но я не могу предсказать все, что вам нужно сделать. Если вы столкнетесь со структурой, которая по какой-то причине не работает, возможно, стоит задать еще один вопрос SO. Большинство проблем с require — это просто вопрос их расположения в правильном порядке. - person Neil Slater; 18.07.2013
comment
Ладно звучит хорошо. Я попробую! Вы повсюду в моих вопросах о Ruby — спасибо! - person tekknolagi; 18.07.2013