Where Things Go

Rails assumes a certain runtime directory layout and provides application and scaffold generators, which will create this layout for you. For example, if we generate my_app using the command rails new my_app, the top-level directory for our new application appears as shown in the figure.

images/rails_layout.png
Joe asks:
Joe asks:
So, Where’s Rails?

One of the interesting aspects of Rails is how componentized it is. From a developer’s perspective, you spend all your time dealing with high-level modules such as Active Record and Action View. There is a component called Rails, but it sits below the other components, silently orchestrating what they do and making them all work together seamlessly. Without the Rails component, not much would happen. But at the same time, only a small part of this underlying infrastructure is relevant to developers in their day-to-day work. We’ll cover the parts that are relevant in the rest of this chapter.

Let’s start with the text files in the top of the application directory:

  • config.ru configures the Rack Webserver Interface, either to create Rails Metal applications or to use Rack Middlewares in your Rails application. These are discussed further in the Rails Guides.[90]

  • Gemfile specifies the dependencies of your Rails application. You have already seen this in use when the bcrypt-ruby gem was added to the Depot application. Application dependencies also include the database, web server, and even scripts used for deployment.

    Technically, this file isn’t used by Rails but rather by your application. You can find calls to the Bundler[91] in the config/application.rb and config/boot.rb files.

  • Gemfile.lock records the specific versions for each of your Rails application’s dependencies. This file is maintained by Bundler and should be checked into your repository.

  • Rakefile defines tasks to run tests, create documentation, extract the current structure of your schema, and more. Type rake -T at a prompt for the full list. Type rake -D task to see a more complete description of a specific task.

  • README contains general information about the Rails framework.

Let’s look at what goes into each directory (although not necessarily in order).

A Place for Our Application

Most of our work takes place in the app directory. The main code for the application lives below the app directory, as shown in the figure. We’ll talk more about the structure of the app directory as we look at the various Rails modules such as Active Record, Action Controller, and Action View in more detail later in the book.

A Place for Our Tests

As we have seen in Iteration B2: Unit Testing of Models, Iteration C4: Functional Testing of Controllers, and Iteration H2: Testing Our JavaScript Functionality, Rails has ample provisions for testing your application, and the test directory is the home for all testing-related activities, including fixtures that define data used by our tests.

A Place for Supporting Libraries

The lib directory holds application code that doesn’t fit neatly into a model, view, or controller. For example, you may have written a library that creates PDF receipts that your store’s customers can download. These receipts are sent directly from the controller to the browser (using the send_data method). The code that creates these PDF receipts will sit naturally in the lib directory.

images/app_dir_layout.png

The lib directory is also a good place to put code that’s shared among models, views, or controllers. Maybe you need a library that validates a credit card number’s checksum, that performs some financial calculation, or that works out the date of Easter. Anything that isn’t directly a model, view, or controller should be slotted into lib.

Don’t feel that you have to stick a bunch of files directly into the lib directory. Feel free to create subdirectories in which you group related functionality under lib. For example, on the Pragmatic Programmer site, the code that generates receipts, customs documentation for shipping, and other PDF-formatted documentation is in the directory lib/pdf_stuff.

In previous versions of Rails, the files in the lib directory were automatically included in the load path used to resolve require statements. This is now an option that you need to explicitly enable. To do so, place the following in config/application.rb:

 config.​autoload_paths​ += ​%W(​​#{​Rails.​root​​}​​/lib)

Once you have files in the lib directory and the lib added to your autoload paths, you can use them in the rest of your application. If the files contain classes or modules and the files are named using the lowercase form of the class or module name, then Rails will load the file automatically. For example, we might have a PDF receipt writer in the file receipt.rb in the directory lib/pdf_stuff. As long as our class is named PdfStuff::Receipt, Rails will be able to find and load it automatically.

For those times where a library cannot meet these automatic loading conditions, you can use Ruby’s require mechanism. If the file is in the lib directory, you can require it directly by name. For example, if our Easter calculation library is in the file lib/easter.rb, we can include it in any model, view, or controller using this:

 require ​"easter"

If the library is in a subdirectory of lib, remember to include that directory’s name in the require statement. For example, to include a shipping calculation for airmail, we might add the following line:

 require ​"shipping/airmail"

A Place for Our Rake Tasks

You’ll also find an empty tasks directory under lib. This is where you can write your own Rake tasks, allowing you to add automation to your project. This isn’t a book about Rake, so we won’t elaborate, but here’s a simple example.

Rails provides a Rake task to tell you the latest migration that has been performed. But it may be helpful to see a list of all the migrations that have been performed. We’ll write a Rake task that prints the versions listed in the schema_migration table. These tasks are Ruby code, but they need to be placed into files with the extension rake. We’ll call ours db_schema_migrations.rake:

 namespace ​:db​ ​do
  desc ​"Prints the migrated versions"
  task ​:schema_migrations​ => ​:environment​ ​do
  puts ActiveRecord::Base.​connection​.​select_values​(
 'select version from schema_migrations order by version'​ )
 end
 end

We can run this from the command line just like any other Rake task:

 depot>​​ ​​bin/rails​​ ​​db:schema_migrations
 (in /Users/rubys/Work/...)
 20190425000001
 20190425000002
 20190425000003
 20190425000004
 20190425000005
 20190425000006
 20190425000007

Consult the Rake documentation at https://github.com/ruby/rake#readme for more information on writing Rake tasks.

A Place for Our Logs

As Rails runs, it produces a bunch of useful logging information. This is stored (by default) in the log directory. Here you’ll find three main log files, called development.log, test.log, and production.log. The logs contain more than just trace lines; they also contain timing statistics, cache information, and expansions of the database statements executed.

Which file is used depends on the environment in which your application is running (and we’ll have more to say about environments when we talk about the config directory in A Place for Configuration).

A Place for Static Web Pages

The public directory is the external face of your application. The web server takes this directory as the base of the application. In here you place static (in other words, unchanging) files, generally related to the running of the server.

A Place for Script Wrappers

If you find it helpful to write scripts that are launched from the command line and perform various maintenance tasks for your application, the bin directory is the place to put wrappers that call those scripts. You can use bundle binstubs to populate this directory.

This directory also holds the Rails script. This is the script that is run when you run the rails command from the command line. The first argument you pass to that script determines the function Rails will perform:

console

Allows you to interact with your Rails application methods.

dbconsole

Allows you to directly interact with your database via the command line.

destroy

Removes autogenerated files created by generate.

generate

A code generator. Out of the box, it will create controllers, mailers, models, scaffolds, and web services. Run generate with no arguments for usage information on a particular generator; here’s an example:

 bin/rails generate migration
new

Generates Rails application code.

runner

Executes a method in your application outside the context of the Web. This is the noninteractive equivalent of rails console. You could use this to invoke cache expiry methods from a cron job or handle incoming email.

server

Runs your Rails application in a self-contained web server, using the web server listed in your Gemfile, or WEBrick if none is listed. We’ve been using Puma in our Depot application during development.

A Place for Temporary Files

It probably isn’t a surprise that Rails keeps its temporary files tucked in the tmp directory. You’ll find subdirectories for cache contents, sessions, and sockets in here. Generally these files are cleaned up automatically by Rails, but occasionally if things go wrong, you might need to look in here and delete old files.

A Place for Third-Party Code

The vendor directory is where third-party code lives. You can install Rails and all of its dependencies into the vendor directory.

If you want to go back to using the system-wide version of gems, you can delete the vendor/cache directory.

A Place for Configuration

The config directory contains files that configure Rails. In the process of developing Depot, we configured a few routes, configured the database, created an initializer, modified some locales, and defined deployment instructions. The rest of the configuration was done via Rails conventions.

Before running your application, Rails loads and executes config/environment.rb and config/application.rb. The standard environment set up automatically by these files includes the following directories (relative to your application’s base directory) in your application’s load path:

  • The app/controllers directory and its subdirectories
  • The app/models directory
  • The vendor directory and the lib contained in each plugin subdirectory
  • The directories app, app/helpers, app/mailers, and app/*/concerns

Each of these directories is added to the load path only if it exists.

In addition, Rails will load a per-environment configuration file. This file lives in the environments directory and is where you place configuration options that vary depending on the environment.

This is done because Rails recognizes that your needs, as a developer, are very different when writing code, testing code, and running that code in production. When writing code, you want lots of logging, convenient reloading of changed source files, in-your-face notification of errors, and so on. In testing, you want a system that exists in isolation so you can have repeatable results. In production, your system should be tuned for performance, and users should be kept away from errors.

The switch that dictates the runtime environment is external to your application. This means that no application code needs to be changed as you move from development through testing to production. When starting a server with the bin/rails server command, we use the -e option:

 depot>​​ ​​bin/rails​​ ​​server​​ ​​-e​​ ​​development
 depot>​​ ​​bin/rails​​ ​​server​​ ​​-e​​ ​​test
 depot>​​ ​​bin/rails​​ ​​server​​ ​​-e​​ ​​production

If you have special requirements, such as if you favor having a staging environment, you can create your own environments. You’ll need to add a new section to the database configuration file and a new file to the config/environments directory.

What you put into these configuration files is entirely up to you. You can find a list of configuration parameters you can set in the Configuring Rails Applications guide.[92]

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.152.99