In this lesson we’ll improve our application further by sending an email upon a successful payment. The process of handling emails in Rails API is almost the same as it is in regular Rails.
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
In this lesson we'll focus on sending email after performing a payment. So the user wants to have access to the receipt, and that's why we have the email property already established into the order model. In the order payer class you see here, we want to introduce that specific feature. I want to have some part of the code here that does exactly that, it sends email. So we're going to have to do a couple of steps to achieve this. So what we want to do now is to actually notify the user so I'm going to create that message right here or actually right here. If the receipt is created I want to notify the user. This method will be a private method here in the class, so let's just type in private and define that method, notifyuser. This method right here will basically resort to a mailer and deliver it, so we use something like an ordermailer.sendreceipt for example. And we'll pass in that order object and we'll choose to deliver it. Now in Reals4 and Deon we have the option to deliver now or deliver later. This was introduced in 4.2, so we're just gonna stick to deliver later because if we don't have something like Sidekick, or anything like that, it will straight deliver it now. So it's always best to just use deliver later unless you want to be very specific about it. Otherwise, just use deliver later. Now this order mailer class doesn't yet exist. We're going to create it right away. We use rails api g mailer. Actually just using rails would be the same in this scenario but since you already know about the rails five merge with rails API this is totally relevant. Let's stick to rails generate mailer and then order_mailer. The only method that we'll have their is actually the one we've specified in the method. It's going to be called send_receipt. So we'll send it right here. As you see, we have the order mailer, the application mail which is the default class it inherits from and then some test. So now that we have that mailer we can open it up and see a couple of things that we need to have. In this specific scenario we have a greeting which we really don't need and then we can specify an order variable here, which we'll be able to use in the email message. And also, we wanna make sure we type in a subject directly. So we use subject and say something like receipt for order, let's see, we'll inject the order's ID in here. So basically we'll have that ID of that order specified in the subject. Now in terms of the body of the email, we're going to have to do something outside of the ordinary. Because this is rails API it doesn't have a views folder, which we'll have to create by the way. Now, inside here, we're going to have an order_mailer folder, like so. And this will have the send_receipt.text.erb file in order to include the body of the email. Then I'll paste the snippet of code that contains the small template. There, so we are going to greet the person where she's enclosed in the order's name. Then a small text, a list of items as you can see here, and then the total amount for that order to be paid, or that it was paid before. So this is just a very small template for the receipt. Of course you can always create a send_receipt.html.erp. But I'm not gonna do it because I really not a fan of it. And also it is just a duplicate of this content. So for now, it's not needed. You can do it yourself of course. Just create a duplicate with the HTML extension over text, and fill in with html. The one you find best. Now, as far as the template goes, we're done. Now let's focus on the order_mailer again. We need to first inject the order instance variable so it can be read by the template. So we use something like this, the subject is fine now. And then all we need to do is to configure the email settings so let's go to Config > Environments and then maybe either Development or Test. If you wanna test things out live by yourself you can use Developement.rb. Or if you want to perform a test, then you just type in test like so. Actually, I'm gonna go to the test.rb file, because I want to create a test that effectively reaches out to the application, which in turn will send that email. So let's see, let's go to this action mailer parameter here and add in some options. So we'll use config.actionmailer.smtp settings and then this is going to be a hash. And also, this delivery method test, we'll switch it out to smtp. Let me just comment this out really quick, and use smtp. As far as the smtp goes, let me just paste my usual configurations, which will resort to batch variables in everything. There, as you can see, we are specifying the user name, password, address and this special option that I needed to disable this kind of security issue. So depending on your provider settings, you might want to use different values or different configurations. I'll leave a link in the description below for you to learn about all of these settings. For now this is all I need. The variables that I have here are in my own private configuration files, but you can type those manually right inside. So now that this is taken care of, we can continue our development by providing an actual test. Because this is the test environment it is suppose to be used with a test. So we're gonna go to orders_test here and actually I have this can be paid test. This is the one that's going to resort to the pay method, it is going to call it and because of that there's really little that I can do in order to accomplish it. So what I wanna do here is for example to create two items or to add two items to the order. So something like order.order_items.create and then will pass an item ID like so. We're gonna do this like two times. So just add in two times with that block. This means that we'll have two items in that order. And we should have the pay method which would send an email with those two items. Or at least one of them with that quantity updated. So let's see if this actually works. Of course, this is prone to have errors due to the fact that we are trying to configure stuff for the first time, and maybe we need to tweak something. So we'll run this very test by typing ruby, include the test directory like so, and then test/integration/orders_test. Let's try and do this. I'm gonna load it, and there you go. We are missing a template. Under layouts/mailer. So, let´s do that as well. Let´s go to app, views, layouts, and then mailer.text.erp. Let's open it and type something like, for example, the name of our application, and then, for example, a line that separates everything. And finally, we're just gonna yield the remainder of the content. There you go. So much like a standard rails application, you will need a layout doubled with some content, and then yield the remainder. So let's try and run the test again and this time, we have an undefined method for name. So we are reaching to a nil class which means that most likely, something is not being sent properly or not be retrieved properly. Let's check the stat rates. As you can see the template is reaching out to it. We know for a fact that this name call is being referenced correctly because the order instance value is being correctly passed around. The other reference for the name is in here item.item. So we'll need to do some sort of a debugging session here really quick in order to ensure that this doesn't happen any more. So, we're gonna go to the order_mailer here really quick. Let's do a quick binding.pry session here, and we'll just run this test again. We just clear the screen and run the test. As you can see, the order variable is there. So nothing big around them. Now let's go to order items here. It has two what it seems, and then if we try to look up the first one, we will get the first one and then we want to retrieve the item that's associated. Unfortunately, you can see that item is nil. Well, let's see the list of all items. We only have two. Well, that's pretty awkward. The IDs are actually really funky, so this was just the luck of the draw. Let's make sure that the first item, for example, let's update it to be one. So we use .update id:1. Now let's take a look at it again, so item.first. And there you go. Now it has id of 1. So this was just an honest mistake, I mean there's no way we could've guessed this particular situation. So let's just try and run this again, but let me just comment this out really quick. Now, let's clear the screen, and there you go. Now the test is green. The last thing that we need to do is to actually try and send it correctly. As you can see, the email is being sent to this dummy looking string. And we're going to replace it with order.email. If I load the rails console here, I want to make sure that all orders have at least an email. So we'll map this to be a list of all of the emails. So, email right here. And you can see that all of these match what we were supposed to have. However, there is a slight variation here. I want to make sure that the order's email here is the one we are supposed to have. So we're going to run this test again with that prior binding and making sure that the order has the correct email and it does. It will go straight into my inbox. So letting the test run I should have an email being sent properly. As you can see, this is the receipt. We have the list of items and then the total amount. So there you go. We have successfully implemented email capabilities. Even though we have used the test environment, that's really okay. All you need to do is configure the appropriate environment by going to let's see, config, environments and then both development and production. At least production is mandatory, of course. But depending on what you wish to do, configure the appropriate environments.