6

I am trying to learn Middlewares and been practising how to mount it in the Rails application. I have followed the railscast

So far I have implemented these steps:

1) Created a new Rails 4.2 application called: Blog

2) Added a file in the lib folder named as response_timer.rb.

class ResponseTimer
  def initialize(app)
    @app = app
  end

  def call(env)
    [200, {"Content-Type" => "text/html"}, "Hello World"]
  end
end

3) Added config.middleware.use "ResponseTimer" in application.rb.

config.middleware.use "ResponseTimer"

But as i'm hitting the command rake middleware in the terminal, it is reporting this error:

rake aborted!
NameError: uninitialized constant ResponseTimer

I tried also to add the config.middleware.use "ResponseTimer" in the development.rb but again facing the same error.

What am i missing here?

Please help.

Referenced article: http://guides.rubyonrails.org/rails_on_rack.html

Hashmita Raut
  • 171
  • 1
  • 7

2 Answers2

5

Middleware has to have an accompanying module / class, and needs to be loaded in the app before it can be referenced. The way to do this in Rails is with autoloading (lib files aren't autoloaded by default):

#config/application.rb
config.autoload_paths += Dir["#{config.root}/lib/**/"]
config.middleware.use "ResponseTimer"

The above should work for you.

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • 2
    `autoload_paths` is not working :( If I do `rails server` then `uninitialized constant Blog::Application::ResponseTimer (NameError)` And If I do `rake middleware` then `NameError: uninitialized constant Blog::Application::ResponseTimer ` – Hashmita Raut Jan 19 '16 at 10:44
  • Note, in Rails 5+ you can no longer use the String for the name of the middleware. You need to use the proper class name. Additionally, according to @rafaelfranca (Rails core), _"middleware can't be in app because they can't be reloaded. They should be in lib and if you put them in lib, require_relative will work."_ https://github.com/rails/rails/issues/25525#issuecomment-479941866 – Joshua Pinter Nov 02 '20 at 03:02
-2

I followed this answer: https://stackoverflow.com/a/24122424

I tried it before but maybe missed something before.

In appliation.rb

require 'rails/all'
require_relative '../lib/response_timer'
module Blog
 class Application < Rails::Application
  ...
  config.middleware.use ResponseTimer
 end
end
Community
  • 1
  • 1
Hashmita Raut
  • 171
  • 1
  • 7
  • You shouldn't have to include the file explicitly, it's an [antipattern](https://en.wikipedia.org/wiki/Anti-pattern). – Richard Peck Jan 19 '16 at 08:57
  • @RichPeck I am sure what you have pointed out is absolutely correct but `config.autoload_paths += Dir["#{config.root}/lib/**/"]` isn't this line doing the same stuff except its calling the entire `lib` folder where as in the given answer its just calling one file. can you please explain a bit. – Abhinay Jan 19 '16 at 09:35
  • It's autoloading the lib folder, so you don't need to explicitly call the files you need in your `application.rb`. – Richard Peck Jan 19 '16 at 09:37