2.5 Providing Statistics
In this lesson we'll create a statistics endpoint that will support some useful indicators for our business. The possibilities are immense—we'll explore just a couple of them in this lesson.
1.Introduction3 lessons, 12:00
1.2Model Our Business Data05:37
1.3Installing Rails API04:16
2.Building the API10 lessons, 1:53:48
2.3Adding Items to Orders14:45
2.4Payments and Receipts11:05
2.6A Refactoring Opportunity13:34
2.9Active Model Serializers08:51
2.10Documenting Your API14:07
3.Conclusion1 lesson, 01:08
2.5 Providing Statistics
In this lesson, we'll provide some statistics. Nothing too fancy, but just a small feature that really goes outside of the box. We're gonna create our very own controller with our very own action without resorting to too many generators. Also, the code that we're going to present to the user is really something that can only be done by hand. So let's start by generating the only thing that we'll need, which is a controller, and we'll call it stats controller. We're gonna have an index action, and that's it. If you press Enter, you will see that a route will be added, as well as a controller and a test. Now let's go to app/controllers/stats. That's basically what we need, we need a basic stats controller with an index action. In here, we're going to render a JSON file, which will basically be something like this. It will have an orders key, which will match a specific set of orders, which we'll fetch right up next. Then we're also going to have a customers variable, which I'm going to pull it out to customers, like so. And also a list of orders_by_month. So we're going to create that key and the respective message. Remember that these statistics are the ones that I thought of that could be valuable for some reason. But you can also add your own. So let me just go ahead and strictly take care of the routes. As you can see we have stats/index. That's really not what I want. I want to delete this and just provide a /stats, which will point out to stats#index. That's much more like it. So I'll go to the StatsController in the index method. As you can see on the right side of the method, which will be represented by /stats, that's it. Now let's go back to the StatsController. As I've mentioned, we're gonna have three indicators. I made these indicators up myself. Now as for the orders, I can go and retrieve them by typing Order.all. That's basically it. Actually if you want to, just to be consistent, you can create a method that will just retrieve those. That way you won't mix messages with instance variable. So, let's create that method called orders, like so, which will point out to Order.all then we're going to create the customers method and also the orders_by_month method. As of now this Ruby code is correct, it doesn't have any syntax errors whatsoever. However, we still need to complete both of these methods. Now around the customer's challenge. You know for a fact that customer's data is held in the orders. So, regarding the orders, it is actually pretty good that I add the orders instance variable like so. And then I'm going to retrieve them the same way as I would in line four. So I'll reach for the orders. And I wanna create a mapping on top of those orders, and filter only the name of the customer. So we'll use map, for example. Each one will be the order passed as an argument to the block. And what I want is just the orders.name. In fact, you can do something like this, orders.map and then let's add in an &:name. The two lines you see here are exactly the same, so I'm just gonna comment this one out, and we're good. Oh, by the way, I don't just want the name. I wanna group them by, for example, a specific number of times that they've come. So instead of doing a simple mapping, I'm gonna do something else. I want to group them by names, so I use the group by instruction. And this will give me a representation, or at least a hash, with the name as the key, and then the respective order objects. In this particular case, I want to filter these out with an array. I wanna create a new representation that's going to be an array, and I want the name and the count of all of the orders. So instead of order, rather orders, there you go, and now the elements that go into the hash are the key first, which is the name, and then the list of orders. Remember, the group_by method will group all orders by a common term, the one that makes it unique. If we have more than one order per customer, we will have that list of orders with that key. So, let me just delete that line for a second. And this will give us a list of arrays with the name and the count of all of the orders that he has taken in the restaurant. Basically this keeps track of how many times the customer has gone to the restaurant. As far as the orders_by_month go, we're gonna use a similar operation. Instead of grouping by the name, we'll group by something that goes into this block. The block will take an order, which is each one of the orders. So we'll go to order and we'll reach out to the created at variable, which is a time variable. It will use this instruction in specific. This one is related to Rails actually, active support contains this very method, beginning_of_month. beginning_of_month will take something like this, let me figure this out. If you have for example let's see, Jan 04. And then another Jan but this time for example 06. And then Feb 19. Imagine you have a list of these three dates. The method considers the year inclusive, so we're gonna pick up on that but just disregard it for a second. What this method will do, is it will group the generated timestamps into one single array and the February on the other one. The key that we'll have is the month. So we'll have a proper representation of the number of folders that were taken at each different month. Now I wanna create a similar mapping with the month and the list of orders. And then we'll create a similar array as you see on top. We want the month and the orders.count, and that's it. So, if we have, for example, 10 orders in January and 15 on February, we will have two entries. The first one will have January 2015 with 10 orders, and then February 2015 with 15 orders. And that's it. This is how we accomplish some sort of a statistics panel. Remember that all this data should be consumed by some application out there. Maybe a or an Angular application, or even a native app in iOS, or Windows, or something like that. The sole purpose of building an API is to render data so other applications can use. That's exactly what we are doing here. As usual, we'll go to bin/curl, and we'll create yet another function. I'll just print out a stats function, there you go, and then just type in curl http://localhost:3000/stats. Since we are creating a GET request, we don't need to do anything else. Of course that this instruction is so simple that we might not needed it. But still, it's there and we can use it by typing bin/curl stats. You will see so much stuff here. Let's see, we have a list of orders, there's the first one, and maybe this is the second one. Then the customers, for example, here we have an array with my name and 2 orders, and the orders_by_month is also there. You can see September 1st because this is September that I'm recording. And then to orders. So there you go, we've implemented the statistics on our application. Depending on what indicators you want to provide, you implement as many different keys in the hash and it will rendered just as easy.