Gosh, Wouldja Look at the (date)time!
When building an API in Rails with a Javascript frontend, you may encounter the need to store and display dates and times. This can be difficult, seeing as Ruby’s datetime datatype and Javascript’s Date object are, well, completely different things. The following is a simple (like, really, really simple) primer on how to work with dates in a Rails API and a Javascript frontend.
But first: why the hassle? Why not just save dates as strings and Rails and be done with it? Well, it’d be a shame to sacrifice the inherent functionality and data contained in Ruby datetime. Plus, if you want to do anything at all with your date information on the frontend, you’ll need to convert it anyway.
Second: buyer beware. This is by no means an exhaustive explanation of either the datetime datatype or the Date object, and I’m by no means an expert. In fact, it’s because of my very lack of expertise that I felt the need to write this blog post. There’s frankly a TON of information out there on this subject, but if you’re a beginner programmer trying to figure out how to work with dates in a Rails API, you’ve come to the right place.
Backend: I’m going to use the code I’ve written for a bare-bones mood-tracker app to take us through the setup. To create the backend, enter the following line of code (emphasis added) into your terminal. Not sure whether to use model, resource, or scaffold? Check out this helpful article to learn more.
rails g [model, resource, or scaffold] Mood mood_level:integer date:datetime
Then run rails db:migrate
to migrate your table to the database. You should see the following:
Now, you might be thinking, why make a date column when you could just use Rails timestamps? Great question. More on that in a bit. First, we need to display our dates in a legible way!
Frontend: Once we’ve got our server up and running and a browser window open, we can demonstrate the different ways to use Ruby’s datetime format in Javascript. For starters, logging the .date
property of a mood object to the console will give us the following: 2019–12–18T00:00:00.000Z. While legible, this object (a string, by the way) isn’t all that legible. What we want to do is convert it to a JS Date object. Let’s try the following:
moodDate = new Date(moodObj.date)
console.log(moodDate)
That should give us a slightly-more-legible date object: Tue Dec 17 2019 19:00:00 GMT-0500 (Eastern Standard Time). However, there’s a lot of information here that we don’t really need. Here are a few ways we might format the above date object to display in the :
moodDate.toDateString()
“Tue Dec 17 2019”moodDate.toLocaleDateString()
“12/17/2019”moodDate.toLocaleString()
“12/17/2019, 7:00:00 PM”moodDate.toUTCString()
“Wed, 18 Dec 2019 00:00:00 GMT”moodDate.toISOString()
“2019–12–18T00:00:00.000Z”
Hey, look at that! That string looks a hell of a lot like a Ruby datetime format, doesn’t it? This brings us to our next step: saving dates from the browser to the database. (By the way, there are a lot more JS Date formats you might find useful. For a deep dive into the many ways to format Javascript’s Date objects, including .toJSON()
, I’d recommend this article from CSS Tricks.)
When pulling a date from from, say, an HTML form, we want to make sure that our information is properly formatted to be saved to a database. With .toISOString()
, it’s a pretty simple task. Say, for example, you’re trying to store an object with the current date and time as a property. To get the current date and time, you’ll want something like
const date = new Date(Date.now())
Conveniently, you can use this variable in a as an object’s .date
property in a fetch() POST request! Simply save it to a new object or put it directly into your request’s options
object:
body: JSON.stringify({mood_level: parseInt(form.mood.value), date: date})
Now to your earlier question: why make a date column when you could just use Rails timestamps? The answer is because this way, we’re able to persist data from the API to the browser and back again. It’s easy to manipulate on the frontend and easy to read on the backend. And that’s it! Boy, does time fly when you’re talking about time in programming.