I can't believe it's saturday already! Day four of the vlog, we're working on simple_calendar again. Today I'm not quite sure what I want to do. We've got Rspec added to the gem, we've made some progress. I wanted to review these last three pull requests that we've got, because I think that they actually are features I'd like to do before we refactor the gem, but maybe not, we'll take a look and see what we've got. This first one, "Update week_calendar.rb", we were talking about a work week calendar which would be like a monday through friday work week instead of sunday through saturday or monday through sunday depending on where you are in the world. I think that would be really cool. I also think it's not a feature that we have to add necessarily, this actually makes perfect sense for our refactoring. So what I want do is just talk about goals here. So this calendar class in our gem is the bread and butter of everything that we have. It is the thing that takes the dates, renders the calendar, it does everything, and it's the one also with the time zones, it knows the events, it knows all of the configurations that we want, so if we display a week long calendar, that's going to be different from a month calendar. A month calendar will be a lot different there, and I actually want the raw calendar to be this flexible thing that you can set the range of dates that you want to display, and then that way you can configure it to be week, work week, a four day mini calendar thing, a single day, a month, maybe you want to do a six month calendar, I don't know, it doesn't matter. I want this calendar to be really flexible so that people can override that, but what I realized is that I wanted to make this really easy to use, but that's actually pretty complicated, if you're trying to make a calendar that can do all these things, that's a lot of work. What we need to do actually is re factor this so that, number one: Making changes to these options is a lot easier, this is really complicated. We don't want you to have to write these 10-15 line methods. It's not good. Number two: We want to be able to tell you to use your regular ruby code, create a class, inherit from the calendar, and then use that and make your own view helper I think, because that is going to save a lot of trouble, and we may actually want to skip these view helper methods, I'm not sure, I can just instantiate a new calendar in the view, and then render it out. That might be simpler than having to deal with these view helpers, because all they actually do is they require you to have a block, and they render the calendar, so there's nothing magical to it. So it makes sense to maybe kill these off because they are not that helpful. We can have view helpers or something in the README or a video or something explaining: If you want to simplify this to your views, you can create these helpers, but it's not really saving anyone time to do this. I like the idea of taking this and extracting in a way into classes that you can customize in your application, we should just give you advice on where should you put the calendar's class files inside your rails app and how you should do that.
We can talk about all of these different ways of doing this, but I think the best way to do this is to start writing the code we ideally want, and then working backwards, so we write some code that we think we want in some specs, and work backwards into riding past code that passes those tests, and then we can document that and put it in the README and document how it works. This is basically test driven development. You write your tests, you make the code to pass the test and then you refactor it if you need to. You almost always want to refactor it. We're going to take a look at doing that, and thinking about the ideal scenario of how to write calendars and custom calendars in your application, I think as the author of the simple_calendar gem, we want to provide you at least a month calendar, the week calendar and maybe a flexible length calendar. Maybe we'll have an option for that, but all of the rest of these, I think like the work week calendar, and all of the more custom ones, I wanted to make it so that you can easily make the calendar file in your rails application, and then take that and then use the override method name to go and create that. So we're going to have to do a lot of well documented method names, lots of very very clean classes so that you know what to override to achieve that work week calendar for that. We'll probably need the link to the next iteration of the calendar, if it's a work week calendar you might just want monday through friday so the next link gives you the date for the next monday. That's stuff you have to customize and do all of those things with, and we're going to leave that up to you as the author of the calendar and we're going to let you customize that. Let's dive into making our first spec for the month calendar, I think I'm going to leave it there today, let's do that. I'm in the master branch, and I think this is a thing where we should start talking about master branches. I think we want to do a new branch, so we can say:
git checkout -b 2.0 and this will create the new branch for simple calendar version 2.0, I think this is wise for us to go and make a whole new version of it. It won't maybe be that incompatible with stuff before, but it will be incompatible enough, I think it's good to just rethink it all. So maybe it should be named 1.2, I'm not sure, I think 2.0 is fine. It really doesn't make a huge difference, so yeah, let's go from here. Because we're going to plan on changing all the method names, I think we definitely want to use 2.0 rather than 1.2. It's not going to be a small improvement over the method names that we're using before, I think it's going to be a mayor change, because I really want to rethink this gem from scratch, so let's call it 2.0 and call it a day. Let's just start with the README, we just need to be starting with something where we can think about this new version from a holistic perspective, so we're not going to release this for a while, so let's do
gem "simple_calendar", github: "excid3/simple_calendar", branch: "2.0"
if you check out this branch on GitHub you'll see the instructions for this version and using it from the master branch, or the 2.0 branch.
This will use it from GitHub and then you can specify the branch to check out when bundle installs the gem. That should work, we'll test it out in an application and we may need to generate a rails application inside of our rspec directory so that we can use that and test against that, that is something that seems a little overkill but it's not really a bad idea. Devise does this, and you can see in their tests directory, rails_app, this is a whole rails app that is used in order to test devise, so they use it to set up the users, and ActiveRecord users and all of that, and make sure that it's working like necessary, so it's actually a lot of stuff, and it's not a bad thing to test your gem against that. We may not need to go that far but we'll see. Once we get into the usage section, you can see we have examples of how to use the month calendar. This is the most basic, this is what I was shooting for, which is great and a lot of people are happy with that, but it's not as flexible as being able to customize their own calendar, and a lot of people want to build calendars that are very very unique. This approach was great for simple thing, but we also want to add this new ability to make your own calendars in a lot more flexible matter. Let's dive into that.
I think the best place to start is our specs. We have this first spec for the version number and that's good, and make sure that the gem is functioning, which is important. I think we need to start writing a calendar spec, and it probably makes more sense to start from the month calendar because it's the traditional thing when you think of adding a calendar into your application, usually you think of displaying the whole month like google calendar would, or apple calendar, or anything like that. Let's make a spec for that calendar. We make a directory
mkdir spec/calendars, here we can write our month calendar spec. Popping back into vim you can see the calendar's folder is here now but it's empty, and let's just create this spec spec/calendars/month_calendar_spec.rb and here we can get the spec helper. This time we're going to describe simple calendar month calendar. This is already something we've defined, but we're just going to start writing the specs that we want to have.
We want to test that it renders a full calendar months, this should test that it shows the fist day of the month and the last day of the month, it should also make sure that maybe there's an option for it, maybe not. Because I like square calendars, I don't like the ones that don't show... If the first day of the month is on a Thursday, most calendar like Google Calendar especially show the days from Wednesday through Sunday at the beginning of the week from the last month, we actually want to jump to the beginning of the week, and we want to make a spec so that we can make sure that that happens and gets rendered out. It needs to render the days of next and previous months on the edges of the calendar. We might come back to this tomorrow and have a much better way of putting that, that's maybe it.
require 'spec_helper' describe SimpleCalendar::MonthCalendar do it 'renders a full calendar month' it 'renders the days of next and previous months on the edges of the calendar' it 'renders 4 weeks at a time' end
What we really just need is for a month calendar, it just needs to display the whole calendar month, it needs to have that many days, maybe we need to talk about the weeks are broken up accordingly, that might be something. "It renders 4 weeks at a time" or something, it's one of those things where I'm not sure. Maybe if we go to the calendar and take a look a this. Here's the Apple calendar, and it shows the 31 of may, and it shows actually all the way up to the 11th of July, which normally you wouldn't see this empty row because there's no dates in there for that month, which is really interesting. I guess let's play with this a little bit, and see what we find. This is one where it shows 6 weeks of the calendar because may is two days in that one week, and then one day and the very last one. So maybe it's one of those exceptions where it goes six weeks long, maybe we need to include something like that in our tests. Maybe we don't. I don't really think it's necessary, as long as we have a test somewhere that says: For the regular calendar, it splits at the end of weeks, and that would be a test for simple_calendar main calendar overarching class, so this month's calendar is going to inherit from that, and we want this to define that for a month calendar the dates are going to be this range, and then it will split at certain periods. Maybe that's what we need to start with, we can do a couple of these tests but it clearly walks us in the direction of like: What does a generic calendar do? Let's do that, let's go into spec, but this time let's do
require 'spec_helper' require 'rails' require 'simple_calendar/calendar' describe SimpleCalendar::Calendar do it 'has a range of dates' it 'can split the range of dates into weeks' it 'has a title' it 'has a next view' it 'has a previous link view' end
Let's leave it at that for today. We've started our tests, we'll pick them up tomorrow, maybe we'll think of some stuff in the meantime, but this is a good start, we can run our spec and see where we're at. All of these should fail. We need to improve the way we do these requires, but sometimes it's good just to have this as a simple as this is so that you know in each of your specs what's required. This
require 'rails' actually should belong inside of the other file, so like the calendar.rb should be the one that
require 'rails', so if we do this, and we remove it from the specs, this is going to make the test run again. If we do run rake, our rspec runs, and we see that that works again the tests actually get through. We have seven pending tests, and this time we're only requiring the files that are necessary to be tested. That is step one, let's add these to a commit and say
git commit -m "Start writing test for version 2.0" and
git push origin 2.0 branch, and that should be that.
Now we have a 2.0 branch on GitHub which is already displayed here which is awesome, GitHub is amazing, and here we go. This is our first iteration on our 2.0 branch. Tomorrow we will pick up where we left off, maybe we'll make some tests pass, maybe we'll delete all of the code and calendar and start from scratch and rethink it all from the very top down. I think it's probably a good idea so that we can achieve the stuff that we want and we can all talk through it and work through it as we go along. That is all for today and I will see you tomorrow. Peace
Transcript written by Miguel