Many web applications—especially those built with Ruby on Rails—use a layered architecture that is often referred to as a stack, since most diagrams (like the ones used in this book) depict the layers as stacked blocks.
Rails represents the middle of the stack and is called middleware. This is where the core logic of your application lives. The bottom of the stack—the data store—is where the valuable data saved and manipulated by your application lives. This is often a relational database management system (RDBMS). The top of the stack is the user interface. In a web application, this is HTML, CSS, and JavaScript served to a browser.
Each part of the stack plays a crucial role in making software valuable. The data store is the canonical location of the organization’s most important asset—its data. Even if the organization loses all of its source code, as long as it retains its data, it can still survive. Losing all of the data, however, would be catastrophic.
The top of the stack is also important, as it’s the way the users view and enter data. To the users, the user interface is the database. The difference between a great user interface and a poor one can mean the difference between happy users and irritated users, accurate data and unreliable data, a successful product and a dismal failure.
What’s left is the part of the stack where most developers feel most comfortable: the middleware. Poorly constructed middleware is hard to change, meaning the cost of change is high, and thus the ability of the organization to respond to changes is more difficult.
Each part of the stack plays an important role in making a piece of software successful. As a Rails developer, you have amassed many techniques for making the middleware as high quality as you can. Rails (and Ruby) makes it easy to write clean, maintainable code.
Digging deeper into the other two parts of the stack will have a great benefit for you as a developer. You’ll have more tools in your toolbox, making you more effective. You’ll also have a much easier time working with specialists, when you do have access to them, since you’ll have a good grasp of both the database and the front end. That’s what you learn in this book. When you’re done, you’ll have a holistic view of application development, and you’ll have a new and powerful set of tools to augment your knowledge of Rails. With this holistic view, you can build seemingly complex features easily, sometimes even trivially.
You’ll learn PostgreSQL, Angular, and Bootstrap, but you can apply many of the lessons here to other data stores, JavaScript libraries, and CSS frameworks. In addition to seeing just how powerful these specific tools can be, you’re going to be emboldened to think about writing software beyond what is provided by Rails.
If all you’ve done with your database is create tables, insert data, and query it, you’re going to be excited when you see what else you can do. Similarly, if all you’ve done with your web views is sprinkle some jQuery calls to your server-rendered HTML, you’ll be amazed at what you can do with very little code when you have a full-fledged JavaScript framework. Lastly, if you’ve been hand-rolling your own CSS, a framework like Bootstrap will make your life so much simpler, and your views will look and feel so much better.
In this book, we focus on PostgreSQL (or simply Postgres) as our data store—the bottom of the stack—and Angular (or just Angular) with Bootstrap as our front end—the top of the stack. Each of these technologies is widely used and very powerful. You’re likely to encounter them in the real world, and they each underscore the sorts of features you can use to deliver great software outside of what you get with Rails.
With these chosen technologies, our application stack looks like this:
In each chapter, I highlight the parts of the stack you’ll be focusing on and call out the various aspects of these technologies you’ll be learning. Not every chapter focuses on all parts of the stack, so at the start of each chapter, you’ll see a roadmap like this of what you’ll be learning:
Let’s get a taste of what each has to offer, starting with PostgreSQL.
PostgreSQL[1] is an open source SQL database released in 1997. It supports many advanced features not found in other popular open source databases such as MySQL[2] or commercial databases such as Microsoft SQL Server.[3] Here are some of the features you’ll learn about (and I’ll show you how to use them with Rails):
You can create highly complex constraints on your table columns beyond what you get with not null. For example, you can require that a user’s email address be on a certain domain, that the state in a U.S. address be written exactly as two uppercase characters, or even that the state in the address must already be on a list of allowed state codes.
While you can do this with Rails, doing it in the database layer means that no bug in your code, no existing script, no developer at a console, and no future program can put bad data into your database. This sort of data integrity just isn’t possible with Rails alone.
In many database systems, you can only index the values in the columns of the database. In Postgres, you can index the transformed values. For example, you can index the lowercased version of someone’s name so that a case-insensitive search is just as fast as an exact-match search.
A database view is a logical table based on a SELECT statement. In Postgres a materialized view is a view whose contents are stored in an actual table—accessing a materialized view won’t run the query again like it would in a normal view.
Postgres has support for enumerated types, arrays, and dictionaries (called HSTOREs). In most database systems, you have to use separate tables to model these data structures.
Postgres supports a JSON data type, allowing you to store arbitrary data in a column. This means you can use Postgres as a document data store, or for storing data that doesn’t conform to a strong schema (something you’d otherwise have to use a different type of database for). And, by using the JSONB data type, you ensure that the JSON fields can be indexed, just like a structured table’s fields.
Although you can serialize hashes to JSON in Rails using the TEXT data type, you can’t query them, and you certainly can’t index them. JSONB fields can interoperate with many systems other than Rails, and they provide great performance.
Angular[4] is a JavaScript framework created and maintained by Google. Angular allows you to model your user interface as components, which combine a model, template, and code all into one self-contained class. This means your view is not a static bit of HTML, but a full-blown application. By adopting the mind-set that your front end is a dynamic, connected interface comprised of components, and not a set of static pages, you open up many new possibilities.
Angular provides powerful tools for organizing your code and lets you structure your markup to create intention-revealing, testable, manageable front-end code. It doesn’t matter how small or large the task—as your UI gets more complex, Angular scales much better than something more basic like jQuery.
As an example, consider showing and hiding a section of the DOM using jQuery. You might do something like this:
| <section> |
| <p>You currently owe: $123.45</p> |
| <button class="reveal-button">Show Details</button> |
| <ul style="display: none" class="details"> |
| <li>Base fee: $120.00</li> |
| <li>Taxes: $3.45</li> |
| </ul> |
| </section> |
| <script> |
| $(".reveal-button").click(function($event) { |
| $(".details").toggle(); |
| }); |
| </script> |
It’s not much code, but if you’ve ever done anything moderately complex, your markup and JavaScript becomes a soup of magic strings, classes starting with js-, and oddball data- elements.
An Angular version of this might look like the following:
| var DetailsComponent = Component({ |
| template: '\ |
| <section> \ |
| <p>You currently owe: $123.45</p> \ |
| <button on-click="toggleDetails()">Show/Hide Details</button> \ |
| <ul *ngIf="showDetails"> \ |
| <li>Base fee: $120.00</li> \ |
| <li>Taxes: $3.45</li> \ |
| </ul> \ |
| </section> \ |
| ' |
| }).Class({ |
| constructor: function() { |
| this.showDetails = false; |
| }, |
| toggleDetails: function() { |
| this.showDetails = !this.showDetails; |
| } |
| }); |
It may seem oddly shaped, but it should reveal its intent much more clearly than the jQuery version, despite the extra bits of code. Without knowing Angular at all, you can piece together that when the button is clicked, it calls the toggleDetails button, and if showDetails is true, we’ll show the detailed information inside the ul. This all maps closely to the user’s actions and intent. There’s nothing in this code about locating DOM elements or handling browser events. And, when you need to do fancier or more complex interactions in your front end, writing code this way is still easy to manage.
Unlike Postgres—where there are very few comparable open source alternatives that match its features and power—there are many JavaScript frameworks comparable to Angular. Many of them are quite capable of handling the features covered in this book. We’re using Angular for a few reasons. First, it’s quite popular, which means you can find far more resources online for learning it, including deep dives beyond what is covered here. Second, it allows you to compose your front end similarly to how you compose your back end in Rails, but it’s flexible enough to allow you to deviate later if you need to.
If you’ve never done much with JavaScript on the front end, or if you’re just used to jQuery, you’ll be pleasantly surprised at what Angular gives you:
Angular models your front end as an application with its own routes, controllers, and views. This makes organizing your JavaScript easy and tames a lot of complexity.
Testing JavaScript—especially when it uses jQuery—has always been a challenge. Angular was designed from the start to make unit testing your JavaScript simple and convenient.
Angular views are just HTML. Angular adds special attributes called directives that allow you to cleanly connect your data and functions to the markup. You won’t have inline code or scripts, and a clear separation exists between view and code.
Because of its popularity, there’s a large ecosystem of components and modules. Many common problems have a solution in Angular’s ecosystem.
It’s hard to fully appreciate the power of a JavaScript framework like Angular without using it, but we’ll get there. We’ll turn a run-of-the-mill search feature into a dynamic, asynchronous live search, with very little code.
Bootstrap[5] is a CSS framework created by Twitter for use in their internal applications. A CSS framework is a set of CSS classes you apply to markup to get a particular look and feel. Bootstrap also includes design components, which are classes that, when used on particular HTML elements in particular ways, produce a distinct visual artifact, like a form, a panel, or an alert message.
The advantage of a CSS framework like Bootstrap is that you can create full-featured user interfaces without writing any CSS. Why be stuck with an ugly and hard-to-use form like this?
By just adding a few classes to some elements, you can have something polished and professional like this instead:
Bootstrap includes a lot of CSS for a lot of different occasions:
Just including Bootstrap in your application and using semantic HTML results in pleasing content with good general typography.
Bootstrap’s grid makes it easy to lay out complex, multicolumn components. It can’t be overstated how important and powerful this is.
Styling good-looking forms can be difficult, but Bootstrap provides many CSS classes that make it easy. Bootstrap-styled forms have great spacing and visual appeal, and feel cohesive and inviting to users.
Bootstrap also includes myriad components, which, as mentioned earlier, are CSS classes that, when applied to particular markup, generate a visual component like a styled box or alert message. These components can be great inspiration for solving simple design problems.
It’s important to note that Bootstrap is not a replacement for a designer, nor are all UIs created with Bootstrap inherently usable. There are times when a specialist in visual design, interaction design, or front-end implementation is crucial to the success of a project.
But for many apps, you don’t need these specialists (they are very hard to find when you do). Bootstrap lets you produce a professional, appealing user interface without them. Bootstrap also lets you realize visual designs that might seem difficult to do with CSS.
Even if you have a designer or front-end specialist, the skills you’ll learn by using Bootstrap will still apply—your front-end developer isn’t going to write every line of markup and CSS. They are going to hand you a framework like Bootstrap that enables you to do many of the things we’ll do in this book.
Now that you’ve gotten a taste of what we’ll be covering, let’s talk about how you’re going to learn it.