It’s been over a week since the publication of my last article. It’s been a rather unproductive week in terms of my primary focus but I have been re-establishing some front-end user interface ideas in my mind thanks to Free Code Camp, but something occurred to me the other day that needed immediate attention and (one would hope) wouldn’t take me too long after my previous fun with dates.
In the above referenced article, I wrote about how I was working on the creation of ‘batches’ for a work project and how the GMT/UTC default of Ruby on Rails was messing with some of the functionality I wanted to work with. Though it took longer than it probably should have (as you might have read), I did finally come up with a solution that worked and made all my tests pass. However, I had forgotten one other date manipulation that was just as important as what I went through before.
Creating the Best By Date
We’re making a product that people are going to ingest, and all ingested products in the United States have a best by date on them, so these batches need a best by date as well. The best by date has been established as 90 days from the date of production. For purposes of the current state of this application, the date of production is same as the
created_at attribute of a batch record. That means that establishing the best by date should be a rather simple exercise of adding 90 days to the
created_at attribute after a batch record is created. And, fortunately, it mostly was.
The first step, as always, is writing the test. The test for this is simple. The best by date will be an automatic creation so I just have to configure the initial ‘successful batch creation’ test to look for the best by date, formatted properly, on the same page all the other newly created batch information shows up.
So the steps in this are pretty simple. Write the migration to add the
best_by attribute, as a date, to the batch model, then write the method in the same model to add 90 days to the
created_at date after the batch is created (using our new friend
after_create) and Bingo, Bango, Bongo, Irving (the things that stick with you from Gilligan’s Island ), you’ve got your test back to passing. Well, you’ve almost got it back to passing.
Formatting a Date / The Read & Write Attributes
For those of you reading this who don’t know much about programming or databases (you know, my family and such), it may (or may not) surprise you to find out that dates are stored rather oddly as data within a database. In my experience working with multiple database systems over the past 20 years, the default format for storing a date is of the format
YYYY-MM-DD. For a concrete example, Pete Rose’s date of birth is April 14th, 1941, which you would probably write as 4/14/41, or perhaps 14/4/41. Databases, however, will store that date as 1941-04-14. I’m sure there’s a very good reason that way back when (in the 50s/60s) they were setting up the rules for databases that they decided to store dates this way. I don’t know what it is, and since I”m not a grad student in the history of database design rules and formats, it doesn’t really matter to me why, I just have to accept that it is.
So, when I ask my application to display the best by date, it displays it in the
YYYY-MM-DD format, which is perfectly acceptable of course, but not exactly standard display or user friendly. I want the date displayed in the more expected format of
MM/DD/YY, and because Rails is cool as all get out and built on top of an object-oriented programming language in Ruby, there’s some great solutions.
The solution starts with the method called
strftime (which I have chosen believe stands for ‘string from time’) that allows you to do all sorts of tricky manipulations to a Date, or DateTime, to display exactly what you want from it how you want it. So with our handy
strftime, I can easily display the best by date in the format I want it displayed. I could write out the proper
strftime manipulation of the best by date on every page I plan to display it on, but since I’m never going to want to display it in the default format, why not just tell my application that any time I call the best by date, it should be displayed in the proper
MM/DD/YY format. Now I know you’re saying to yourself, “John, that’s a great a idea, but you’re trying to change default functionality in a programming language, that’s got to be hard.” (Ok you’re saying it if you don’t know anything about programming, those of you who do already know what’s going to happen, but we’re building suspense here folks.). Turns out that it’s not really that hard due to Rails, Ruby and a handy dandy thing called a
I don’t want to get too deep into Objects, attributes, methods, etc…but a little explanation should be given here. Every attribute I create for my batch, through Rails and Ruby, has to ‘built-in’ methods/functions you can use. They are called the
write attribute and the
read attribute. They are pretty self explanatory - the write attribute allows you to set and change a given attribute and the read attribute allows you to ask the application what is the value of said attribute please. In previous versions of Rails, you had to set either, or both, of these attributes, and doing so gave you access to some built-in methods to take advantage of.
For the sake of argument, let’s say the attribute we are dealing with is the
best_by attribute. When I declare that attribute as part of my Model,
best_by are write and read methods, respectively, automatically set up by the inner workings of Ruby on Rails. You don’t have to write a single line of code, and those two will work exactly like they are intended to, but remember, if i called the
best_by method on a batch, I’m going to get a date formatted like
YYYY-MM-DD, and I never want that to happen. Fortunately, because this is based in object-oriented, I can access the original
best_by read method and change it just a little, so that any time in the future I call
best_by on a batch, I get the date format that I want,
MM/DD/YY. The code is pretty simple.
That’s it. One simple line of code rewrites the built in
read attribute for my best_by column and displays it how I want it to. The key is the
super. It gives me access to the original
best_by method supplied by Ruby on Rails and allows me to alter it. No fuss, no muss. (That weird jumble of % signs /’s and letters is me telling the application to display the date how I want it.
Back to my modified batch creation test, and we’re passing. For completeness and accuracy, all tests are run and they still all pass, so a quick GACP and it’s on to the next one.