Upgrade your Rails workflow using visual code maps
Tags: rails, vscode, productivity
Published: 2021-04-29 11:44:49

Hi there, thanks for checking out this post. Some people like to watch, and some people like to read. So, if you're a watcher, check out the video, it's about 10 minutes long. And if you're a reader, the same content is here in the text, along with screenshots, illustrations, and pointers to specific sections of the video. 

## 1. Introduction

As developers, it often feels like all of our time is spent wading through huge file trees, fixing failing test cases, waiting for code reviews and having meetings. What we want is a smooth flow for understanding what code *actually does*, which code is *relevant* to what we’re doing, and we want to be able to *share* as much knowledge as possible with our team.

So, with that in mind, I want to introduce AppMap. 

![How AppMap works](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83x5wbeptx770h3xq4a2.png)

It’s an open source framework that records your code execution into JSON files. And it’s a code editor extension that turns these files into interactive diagrams and useful code analysis. 

## 2. Opening a new Issue

Let’s step through an example that shows how AppMaps can make development more efficient and more enjoyable. 

`00:40` I've created a [branch of the Rails Sample App](https://github.com/land-of-apps/sample_app_6th_ed/tree/appmap-e2e), which is a Twitter clone. Here’s an odd thing we noticed about it - even when you’re not logged in, you can see the feed of any user. 

![User feed, while not logged in](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6c8pi8230dsguymok6a9.png)

If this were a real app, this behavior would be considered a **privacy risk**, because information about you could be scraped off the website by anonymous bots. 

So what if I want to change the app to require login to see the user page? I’d start by opening a new Issue - I might call it “Require login to view a user.”

## 3. Enhancing the Issue description with AppMaps

Now, I would like to communicate as much useful information about this issue as I can. Why? Because the hardest part of development, especially on unfamiliar code, is not writing the code. It’s **building a mental model** of how the code works, and imagining a solution of how it should work. So one of the best things we can do is making it easier to understand what the code really does.  

`01:40` Here’s where AppMap comes into play. AppMap diagrams provide a design level view of the code. The [Dependency map](https://appland.com/docs/how-to-use-appmap-diagrams.html#view-and-interact-with-the-dependency-map) is a conceptual view of how the code is organized. The [Trace diagram](https://appland.com/docs/how-to-use-appmap-diagrams.html#view-and-interact-with-the-trace-diagram) is a drill down into all the details of code execution paths, like parameters, status codes, and SQL. And it’s all linked to source code. 

Now, an AppMap is a recording of a specific scenario. It doesn’t try to show you the entire code base at once. That just doesn’t work, it’s too much information, and most of it is irrelevant to any particular task. So because an AppMap shows you a specific end to end code and data flow, all the code you see, and all the relationships, are relevant to the job you’re trying to do. Code that isn’t relevant simply isn’t in the diagrams; so you don’t see it and you don’t need to worry about it.

Now I’m going to enhance this GitHub issue by adding AppMaps. Often I create AppMaps by recording test cases, but I can also make them by recording the server while I use the app. 

`02:28` I'll begin a "remote recording" with a [`start_recording` script](https://github.com/land-of-apps/sample_app_6th_ed/blob/appmap-e2e/scripts/start_recording). Then I go to the app UI and hit the page that I’m interested in. Then I stop the recording. When I stop it, an AppMap file is created. I’ll name the AppMap, and then I can just click it to open it in VSCode. 

![AppMap in VSCode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bk8sbgck3kk8k3rk8kyj.png)

I’m also going to make an AppMap of the kind of behavior that I want this page to have when it’s fixed. If I click on “followers” I get a login page. That’s what I want the user page to do. 

![Sample App login page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpnmjyowv45lnvp4okra.png)

So I will make a recording of the followers page, too.

`03:56` Now I can open my AppMaps in finder, and zip them. (You can’t attach JSON files directly to GitHub issues). Then, I'll drag the zip over into the Issue.  

Notice that I don’t need to know much at all about Rails or how the solution will work. I’m just recording some relevant aspects of the app and sending them to the developer. Adding an AppMap is like including a screenshot of the UI; but for the backend. It makes the your backend visual; it’s interactive, and has many dimensions of useful data. 

## 4. Using AppMaps to learn and inspect the code behavior

Ok, now I’m going to switch roles, to the developer who’s working on this issue. I’ve pulled down these AppMap files into my local workspace and I’m going to use them to create my code solution. 

`04:31` I will start with the first AppMap, “user page not logged in”.

From this AppMap, I can see one important piece of information, which is the route that shows the user page. I can also go right to the controller action that serves the page. It will be interesting to compare this flow to the second AppMap. 

![User route and controller](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wb3l379fzc63h5dul0m8.png)

From the second AppMap, I can see how the login security works. Clicking on the label `security.require_login` takes me right to the function that requires the user to be logged in; and redirects them to the login screen if they aren’t. 

![Login requirement in the trace view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jlyszyb3ye686ro0o8fu.png)

I can also see that the login requirement is triggered by a `before_action`. 

## 5. Fixing the issue

`05:41` From the first AppMap I know that the user controller handles this request. So, adding `:show` to the [login `before_action`](https://github.com/land-of-apps/sample_app_6th_ed/blob/ddf913a9f5a52273f4ea45d2a2878c7f372affca/app/controllers/users_controller.rb#L2) should fix the behavior. I will update the doc on the method as well. 

Clicking the user route in the UI confirms that the user page requires a login now. 

The next step is to run my tests. I’m expecting to see a test failure, since hitting the user page without logging in first should result in a redirect to the login page. 

![Test failures](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xr8vb767wnu0b9irz0a9.png)

So, I will update the test to expect a 302 redirect if the user isn’t logged in and a 200 if they are logged in. 

`06:21` Once I update the tests, I regenerate the AppMaps. I can review the AppMaps to make sure the code flow matches my expectation. 

The first test is called “profile display while anonymous”. I can find this AppMap and see that the login action is required. It looks up the user ID in the session, and when it’s not found, it sends a redirect. I’ll compress this AppMap file so I can add it to the pull request.

The second test is called “profile display while logged in as the user”. I’ll find this AppMap too, and I’ll see that this time the code flow continues by making SQL queries and rendering the user page. I’ll compress this file also.

## 6. Demonstrating web service changes by auto-generating Swagger

Now, when I submit this code for review, I want it to be obvious to the reviewer how the user web service has changed. 

`08:34` To document the web services, I’m using Swagger. Swagger is a file format that describes the detailed operation of a web services API.

![About Swagger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61fc48nsecbi76a1t0td.png)

But I don’t need to maintain the Swagger files by hand.  I’m using AppMap swagger, which generates a swagger description of all the web services. So, when I change the tests, I also update the swagger yaml by running `bundle exec rake appmap:swagger`. 

Reviewing the git diff, there’s now a [302 status as well as 200](https://github.com/land-of-apps/sample_app_6th_ed/pull/37/files#diff-5a8462ff556bc188fc1ae9e1583488773391a123e796bc612c406d3e25f399f1) for the GET request to the user route. 

![Swagger diff](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0hkpfmdbpds33vktaef.png)

## 7. Opening the pull/merge request

`09:35` I’m ready to open a PR. I’ll attach the AppMaps for the new code behavior. Along with the source diff and the swagger diff, this gives a reviewer a ton of info about what I’ve done and how it behaves. So without much effort, the code reviewer is going to hit that Approve button and merge this change. 

## 8. Wrap-up

`10:11` That’s a quick tour of how smooth and efficient a Rails workflow can be with AppMap. Try it out for yourself at [https://appland.com/docs](https://appland.com/docs). 

Happy Mapping!

### References

* [AppMap Docs](https://appland.com/docs)
* [AppMap for VSCode](https://marketplace.visualstudio.com/items?itemName=appland.appmap)
* [appmap_swagger gem](https://github.com/applandinc/appmap_swagger-ruby)
* [AppMap quick setup video for VSCode](https://appland.com/videos/2021/01/29/visualize-the-architecture-of-your-ruby-app-in-vscode-in-2-and-a-half-minutes/)
* [appmap_swagger quick setup video](https://appland.com/videos/2021/04/02/add-swagger-to-your-rails-project-with-no-code-in-2-and-a-half-minutes/)