Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby inheritance and require order

I am trying to set up a new modularised Sinatra app. This is the relevant folder structure:

- app 
  - controllers
    - application_controller.rb
    - website_controller.rb
  - config.ru 

The application_controller.rb defines the ApplicationController class, requires sinatra/base and, apart from that, doesn't do anything interesting.

The website_controller.rb inherits application_controller.rb:

# website_controller.rb
class WebsiteController < ApplicationController

  include Sinatra::Cookies
  ...
end

My config.ru file is what I run to start the Sinatra app, so it is supposed to require all the classes:

#config.ru
require 'sinatra/base'

Dir.glob('./app/{models,helpers,controllers}/*.rb').each {|file|
  require file
}

...

When it requires all files, it requires website_controller.rb before requiring application_controller.rb. That way, when the inheritance on WebsiteController is parsed, it does not know yet what ApplicationController is, and I get the error uninitialized constant ApplicationController (NameError).

What is the best practice to set up my project so I have all required files ready without facing this kind of ordering problems?

like image 246
Matheus208 Avatar asked Mar 22 '26 05:03

Matheus208


1 Answers

So, the other answer is actually the correct and easiest way - but if for whatever reason you don't want to do it that way, you can use autoload provided you've developed your Sinatra app in the "modular" style.

In config.ru you are currently "eager-loading" all of your files. Instead, you would explicitly list the load paths for unknown constants - like so:

autoload :ApplicationController, 'app/controllers/application_controller'
autoload :WebsiteController, 'app/controllers/website_controller'

Note that autoload is a method on Module so you have to put the calls to autoload within the same 'namespace' - ie:

module MyApp
  autoload :MyThing, 'models/my_thing'
end

Will fire the autoload when the constant MyApp::MyThing is missing. That said - unless you know why you need to autoload your classes, just require it at the top of the file.

like image 194
prater Avatar answered Mar 23 '26 19:03

prater