zuzannast / swagger_ui_engine

Include swagger-ui as rails engine and document your API with simple JSON or YAML files.
https://zuzannast.github.io/swagger_ui_engine/
MIT License
83 stars 43 forks source link

rails 5 api not including ActionView::Layout #14

Closed dhurba87 closed 7 years ago

dhurba87 commented 7 years ago

I've tried to implement this in api-only application and got following errors. It looks like ActionView::Layout is not configured properly in apionly application

Started GET "/api_docs/" for 127.0.0.1 at 2017-08-06 17:46:54 +0545

ActionController::RoutingError (undefined method `layout' for SwaggerUiEngine::SwaggerDocsController:Class):

swagger_ui_engine (1.1.0) app/controllers/swagger_ui_engine/swagger_docs_controller.rb:7:in `<class:SwaggerDocsController>'
swagger_ui_engine (1.1.0) app/controllers/swagger_ui_engine/swagger_docs_controller.rb:2:in `<module:SwaggerUiEngine>'
swagger_ui_engine (1.1.0) app/controllers/swagger_ui_engine/swagger_docs_controller.rb:1:in `<top (required)>'
activesupport (5.0.5) lib/active_support/dependencies.rb:477:in `load'
activesupport (5.0.5) lib/active_support/dependencies.rb:477:in `block in load_file'
activesupport (5.0.5) lib/active_support/dependencies.rb:662:in `new_constants_in'
activesupport (5.0.5) lib/active_support/dependencies.rb:476:in `load_file'
activesupport (5.0.5) lib/active_support/dependencies.rb:375:in `block in require_or_load'
activesupport (5.0.5) lib/active_support/dependencies.rb:37:in `block in load_interlock'
activesupport (5.0.5) lib/active_support/dependencies/interlock.rb:12:in `block in loading'
activesupport (5.0.5) lib/active_support/concurrency/share_lock.rb:150:in `exclusive'
activesupport (5.0.5) lib/active_support/dependencies/interlock.rb:11:in `loading'
activesupport (5.0.5) lib/active_support/dependencies.rb:37:in `load_interlock'
activesupport (5.0.5) lib/active_support/dependencies.rb:358:in `require_or_load'
activesupport (5.0.5) lib/active_support/dependencies.rb:511:in `load_missing_constant'
activesupport (5.0.5) lib/active_support/dependencies.rb:203:in `const_missing'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:270:in `const_get'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:270:in `block in constantize'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `each'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `inject'
activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `constantize'
activesupport (5.0.5) lib/active_support/dependencies.rb:583:in `get'
activesupport (5.0.5) lib/active_support/dependencies.rb:614:in `constantize'
actionpack (5.0.5) lib/action_dispatch/http/request.rb:81:in `controller_class'
actionpack (5.0.5) lib/action_dispatch/routing/route_set.rb:44:in `controller'
actionpack (5.0.5) lib/action_dispatch/routing/route_set.rb:30:in `serve'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:39:in `block in serve'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:26:in `each'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:26:in `serve'
actionpack (5.0.5) lib/action_dispatch/routing/route_set.rb:727:in `call'
railties (5.0.5) lib/rails/engine.rb:522:in `call'
railties (5.0.5) lib/rails/railtie.rb:193:in `public_send'
railties (5.0.5) lib/rails/railtie.rb:193:in `method_missing'
actionpack (5.0.5) lib/action_dispatch/routing/mapper.rb:17:in `block in <class:Constraints>'
actionpack (5.0.5) lib/action_dispatch/routing/mapper.rb:46:in `serve'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:39:in `block in serve'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:26:in `each'
actionpack (5.0.5) lib/action_dispatch/journey/router.rb:26:in `serve'
actionpack (5.0.5) lib/action_dispatch/routing/route_set.rb:727:in `call'
warden (1.2.7) lib/warden/manager.rb:36:in `block in call'
warden (1.2.7) lib/warden/manager.rb:35:in `catch'
warden (1.2.7) lib/warden/manager.rb:35:in `call'
rack (2.0.3) lib/rack/etag.rb:25:in `call'
rack (2.0.3) lib/rack/conditional_get.rb:25:in `call'
rack (2.0.3) lib/rack/head.rb:12:in `call'
activerecord (5.0.5) lib/active_record/migration.rb:553:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
activesupport (5.0.5) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
activesupport (5.0.5) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
activesupport (5.0.5) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.5) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.0.5) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.0.5) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.0.5) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.0.5) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.0.5) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.0.5) lib/rails/rack/logger.rb:24:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/request_id.rb:24:in `call'
rack (2.0.3) lib/rack/runtime.rb:22:in `call'
activesupport (5.0.5) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.5) lib/action_dispatch/middleware/static.rb:136:in `call'
rack (2.0.3) lib/rack/sendfile.rb:111:in `call'
rack-cors (1.0.1) lib/rack/cors.rb:93:in `call'
railties (5.0.5) lib/rails/engine.rb:522:in `call'
puma (3.9.1) lib/puma/configuration.rb:224:in `call'
puma (3.9.1) lib/puma/server.rb:602:in `handle_request'
puma (3.9.1) lib/puma/server.rb:435:in `process_client'
puma (3.9.1) lib/puma/server.rb:299:in `block in run'
puma (3.9.1) lib/puma/thread_pool.rb:120:in `block in spawn_thread'
zuzannast commented 7 years ago

Hey @dhurba87, could you provide me with some information about your app setup? I've generated some API-only example app and cannot reproduce this bug.

zuzannast commented 7 years ago

Also, please note that you can list all the modules included in swagger_ui_engine by running SwaggerUiEngine::ApplicationController.ancestors in Rails console. As this module inherits from ActionController::Base - it should return you the ActionView::Layouts module within other included ones. This one is used when running the gem-specific views.

dhurba87 commented 7 years ago

Here is my app setup Gemfile:

source 'https://rubygems.org'

ruby "2.4.0"

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.2'
# Use postgresql as the database for Active Record
gem 'pg', '~> 0.18'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'

  gem 'awesome_print', '~> 1.7'
  gem 'pry', '~> 0.10.4'
  gem 'faker'
  gem 'swagger-docs'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

# For user authentication
gem 'devise_token_auth'

# Omniauth for Oauth login
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'

# rails app configuration using ENV and a single YAML file
gem "figaro"

gem 'carrierwave', '~> 1.0'
gem 'mini_magick'
gem 'colorize'
gem 'swagger_ui_engine'

config/initializers/swagger_ui_engine.rb

SwaggerUiEngine.configure do |config|
  config.admin_username = 'admin'
  config.admin_password = 'admin'
  config.swagger_url = 'api/swagger.yaml'
end

config/routes.rb

Rails.application.routes.draw do
  ...
  mount SwaggerUiEngine::Engine, at: "/api_docs"
  ...
end

Let me know if you need anything else.

SwaggerUiEngine::ApplicationController.ancestors is including ActionView::Layout but i don't know what is happening. Here is the outout of SwaggerUiEngine::ApplicationController.ancestors


2.4.0 :001 > SwaggerUiEngine::ApplicationController.ancestors
 => [SwaggerUiEngine::ApplicationController, SwaggerUiEngine::AuthConfigParser, #<Module:0x00000002f451f8>, #<Module:0x00000004144fc0>, #<Module:0x00000004144fe8>, ActionController::Base, Devise::Controllers::UrlHelpers, Devise::Controllers::Helpers, Devise::Controllers::StoreLocation, Devise::Controllers::SignInOut, ActiveRecord::Railties::ControllerRuntime, ActionDispatch::Routing::RouteSet::MountedHelpers, ActionController::RespondWith, ActionController::ParamsWrapper, ActionController::Instrumentation, ActionController::Rescue, ActionController::HttpAuthentication::Token::ControllerMethods, ActionController::HttpAuthentication::Digest::ControllerMethods, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionController::DataStreaming, ActionController::Streaming, ActionController::ForceSSL, ActionController::RequestForgeryProtection, AbstractController::Callbacks, ActiveSupport::Callbacks, ActionController::FormBuilder, ActionController::Flash, ActionController::Cookies, ActionController::StrongParameters, ActiveSupport::Rescuable, ActionController::ImplicitRender, ActionController::BasicImplicitRender, ActionController::MimeResponds, AbstractController::Caching, AbstractController::Caching::ConfigMethods, AbstractController::Caching::Fragments, ActionController::Caching, ActionController::EtagWithTemplateDigest, ActionController::ConditionalGet, ActionController::Head, ActionController::Renderers::All, ActionController::Renderers, ActionController::Rendering, ActionView::Layouts, ActionView::Rendering, ActionController::Redirecting, ActiveSupport::Benchmarkable, AbstractController::Logger, ActionController::UrlFor, AbstractController::UrlFor, ActionDispatch::Routing::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, ActionController::Helpers, AbstractController::Helpers, AbstractController::AssetPaths, AbstractController::Translation, AbstractController::Rendering, ActionView::ViewPaths, #<Module:0x000000045eb790>, ActionController::Metal, AbstractController::Base, ActiveSupport::Configurable, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, ActiveSupport::Dependencies::Loadable, PP::ObjectMixin, JSON::Ext::Generator::GeneratorMethods::Object, ActiveSupport::Tryable, Kernel, BasicObject] 
zuzannast commented 7 years ago

@dhurba87 I've used the setup you posted and still got everything working as expected. Could you post your application.rb config aswell? Is the swagger_ui_engine version in your Gemfile.lock pointing 1.1.0? Is your application private or public? I'd love to debug the issue.

dhurba87 commented 7 years ago

I'm sure my Gemfile.lock is pointing 1.1.0 version and my application is private so I afraid I can't give you full access.

Here is my application.rb file


require_relative 'boot'

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Airtasker
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true
  end
end
zuzannast commented 7 years ago

Again - I cannot reproduce this issue and the workaround for it would probably be adding include ActionView::Layouts to your ApplicationController. Could you tell me which Rails version you're using?

dhurba87 commented 7 years ago

Its 'rails', '~> 5.0.2' as i mentioned in the gemfile.

zuzannast commented 7 years ago

Sorry, I cannot reproduce this issue in a newly-generated API-only application using the setup you posted. Please check whether the module is included in SwaggerUiEngine::SwaggerDocsController.ancestors and if not, try including it explicitly inside your ApplicationController. Check whether the actionview is installed inside your Gemfile.lock. Try restarting your spring server aswell. Let me know how that goes.