[ToDoList] Hindsight Exercise (Generators)

Our ToDoList web app is certainly a beautiful thing, and has seen a lot of love as we've done most of the legwork manually. However, as mentioned several times throughout the guide, most of what has been done above can be bypassed with higher-level Ruby magic in the form of generators, which automated a great deal of the work.

This short section will outline which of the steps we've taken to create our app so far could have been automated in this way.
If you want to code along with this section, you can cd back into your projects directory and create a separate Rails app (i.e. to_do_list2) to test these generators as we go along:

$ rails new to_do_list2

  1. Basic Controller Generation
  2. Generating Models
  3. Next-Level Generator Usage

 


 

Our first step was creating our PagesController and its respective views, which seems so long ago now. Doing this manually was extremely valuable to learn how each piece of the application knitted together, but also to appreciate the power of the generator that could have done half the job for us.
The command below invokes the controller generator, where we pass it the name of the controller (in CamelCase) as well as the actions/views that we want it to generate (in snake_case):

$ rails generate controller Pages home about help
      create  app/controllers/pages_controller.rb
       route  get 'pages/home'
get 'pages/about'
get 'pages/help'
      invoke  erb
      create    app/views/pages
      create    app/views/pages/home.html.erb
      create    app/views/pages/about.html.erb
      create    app/views/pages/help.html.erb
      invoke  test_unit
      create    test/controllers/pages_controller_test.rb
      invoke  helper
      create    app/helpers/pages_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/pages.scss

We can see from the output there that this generator has done an awful lot for us - if you ran this yourself go into each file and see what it has done:

  • It has created our PagesController file based on the initial Pages argument we passed.
    • Also it has defined each of the actions we passed in as arguments afterwards: home, about and help
  • It has generated basic routes for us in the config, which admittedly we would have to go in and change.
  • It has invoked erb to create our views directory and a file for each one we passed arguments for.
    • If you start the server and navigate to these pages, you will see some temporary HTML showing that it is working correctly, as well as where to go to change it.
  • It has invoked the TestUnit and created some basic integration tests for our routes.
  • It has added an (empty) helper module.
  • It has generated a template for a stylesheet which can be used to make it pretty later on.
As stated, we still would need to amend the routes configuration as we needed it and add some HTML to our views to complete this step, however Rails' generator would have given us all the bones we needed to create these pages and route them correctly!

 


 

Our actual Todos development was a slightly more involved affair, which required a database to be set up with an associated model on top of controllers and views. You may recall we used a generator here to create a migration file to initially set up our database.
However Rails could have handled even more of this for us if we had used the model generator to do this instead:

$ rails generate model Todo name:string description:text
      invoke  active_record
      create    db/migrate/20210521143142_create_todos.rb
      create    app/models/todo.rb
      invoke    test_unit
      create      test/models/todo_test.rb
      create      test/fixtures/todos.yml

By the output, we can again see that Rails has done a bit of the heavy lifting for us here:

  • It has invoked ActiveRecord and has run the migration generator, which we did manually before to create our migration file.
  • It has created our basic (blank) model.
  • As with the controller, it has invoked the TestUnit and populated some basic tests.
    • It has also generated a fixtures file, which will be used by the test when it is run.
The model spawned by this generator will only define the Todo class using ApplicationRecord as a base, as we did manually before - it will not won't include any validation settings.

 


 

As for the controller, we know from before that the controller generator will create the controller actions, as well as the views, based on the arguments we pass it. But for some actions (i.e. #update, #destroy), we do not require a view. In addition, it will create the routes that it calculates are required. However in the case of the Todos, we know that our magic resources line in the route config will provide all of the routes we need and so we don't need the generator to provide any routes.

We will therefore need to run our controller generator only passing arguments for actions that we would like a view for, and an additional argument that will prevent it adding to the routes configuration to save us deleting it later:

$ rails generate controller Todos show new edit index --skip-routes
      create  app/controllers/todos_controller.rb
      invoke  erb
      create    app/views/todos
      create    app/views/todos/show.html.erb
      create    app/views/todos/new.html.erb
      create    app/views/todos/edit.html.erb
      create    app/views/todos/index.html.erb
      invoke  test_unit
      create    test/controllers/todos_controller_test.rb
      invoke  helper
      create    app/helpers/todos_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/todos.scss
As we can see, the generator has provided all of the resources we requested of it similarly to the one we ran for Pages, without the addition of the routes configuration lines. All we need to do now is add our magic line into /config/routes.rb:
  resources :todos
and populate our action definitions, adding in the ones that we didn't ask the generator to create (eg: #update), in addition to the HTML that we need to perform our CRUD methods from the front end.

Obviously there were some bits generated in this section that we haven't covered previously, such as integration tests, helpers and stylesheets - we may cover these in a later section, however more information can be found in the Ruby on Rails guides at guides.rubyonrails.org.

Even if you choose not to look up these particular features, it is hugely, massively recommended that you go through the Getting Started with Rails guide on this site, which instructs on how to create a simple blog app using these generators (and you can see just how much of this guide I have plagiarised!).
This guide also adds several extra layers of complexity to the app, including nested comments, concerns and basic authentication. It is very educational and very fun!

 


 

However there is one last thing I would like to show you regarding generators that, if you were impressed by what we've seen in this section so far, will leave you in an open-mouthed state of awe (again, this may have just been me).

 
 

Comments

Popular posts from this blog

New Rails Apps with Docker Compose

[ToDoList] Basic Pages

[ToDoList] Docker Compose