Skip to main content
Building A Calendar Gem:

Open Source Vlog - Rails Generators

Episode 77 · July 13, 2015

Today we're adding Rails generators as our final piece of the puzzle for Simple_Calendar 2.0



Earn a free month

So we've been working on simple calendar, we've made some huge progress but the last thing that we really need for this is to be able to install these views into your rails app so that you can override them and build your own calendar styles, that's what we're going to do today and we're going to take a look at rails generators, I'm actually going to google this real quick because it's been a long time since I've actually written my own generator, and I know that there's actually a rails guide on this, so if you take a look at rails guides, the generators files, there's actually some really awesome stuff in here, and there's this thing called thor which allows you to run a lot of command line interface stuff, and it's really useful for this kind of thing because it allows you to write these commands like rails generate simple_calendar:install like you would do with rails g devise:views for example, and it will look up a generator with that name in your gem, and then it will basically do whatever you would like, so you can have it create files, you can have it edit files, you can have it do all these things and there's a lot of stuff that thor helps you do, I think this is super cool and we're going to build one for simple calendar to install the views.

Let's dive in, it looks like we're going to build a file inside the lib directory named generators. If we go to GitHub, and we look at devise's generators, this is a thing that I do often, look up and see what these other gems do, notably this has a file called lib/generators/devise/views_generator.rb so my guess is that this is going to allow you to run that rails g devise:views command, and this directory structure is what you need to set that up appropriately. We already have a lib directory, and inside lib we're going to need a lib generators directory, but we'll also need a simple_calendars directory I believe so we can get that scope properly. Here I'm going to create two folders, so I'm going to use the -p flag to do that, and then we can open up MacVim to create our generator, let's do lib/generators/simple_calendar/views_generator.rb, and we need to grab a couple things here.

module SimpleCalendar
    module Generators
        class ViewsGenerator < Rails::Generators::Base

The way that these generators work is that you define a bunch of methods in there, and then it executes them one by one in the order that you defined them, so it's really really nifty and simple for that, so I believe we can do a few other things, like you can accept arguments and do other stuff like that if you want, and this actually invokes a shared views generator, which you could probably find that class_for, and it includes another module and then a view directory and that's probably the views template path provides that, all kinds of stuff that it's doing here. We don't really need anything near as complicated as they have, so I'm just going to get back to our example here and we'll look at basically copying a directory from our gem and putting it into the app. Thor being our library here that we have access too, it's got all these helpers of how to copy directories and we basically want to copy stuff from our gem and point it right into our rails app, so in theory they've got some great helpers for that. It looks like there's a directory command that does exactly that, so we'll see what happens. We just need to define any method here and this will be executed. This is copy_views, that's what that should be where it goes inside our rails app, and this should be where it comes from should be app/views/simple_calendar I'm not sure if we need simple_calendar in both of these, but I guess we'll just try it out because worst case scenario we can just delete those files, so let's do rake -T, we should in theory see this new simple calendar task, and I don't actually see it, but actually that would be because rails g is a little different and it doesn't show up as a regular rake task, here we can try rails g simple_calendar:views views generator source root path. That's exactly what we need, basically it's saying it doesn't know where to start and we need to set a source root, so let's take a look a thor's documentation here and see if we can find source root.

Let's see if we can find any examples. source_root File.expand_path("../templates", _FILE_) this is a better example, basically we're going to set this inside our generator, but one of the things with this is we want to make sure we go back some directories so this FILE variable is available in every single file in ruby and it gives you the path to the current file, so actually with the views generator, we need to go up two directories, and that in theory should work, so we go from the simple calendar folder to generators folder with two ..'s.

Let's try this one more time to see what happens: "Could not find "app/views/simple_calendar" om any of your source paths. Your current source paths are 'code/simple_calendar/lib'", so we didn't go up far enough. and there we go, we actually now we're getting an override here and it's saying: We're trying to copy this calendar file from the gem into your rails app, you already have it, what do you want to do? Do you want to keep it? We're going to override it, hit enter, and we also copied the other one, so we actually have this override working and that was it, we had to create one file inside some directories, because we're using the rails engine, it knows to load this generators, and it knows how to invoke them automatically because we've created them in the correct directory and we've named them right, and used the examples correctly. The only thing that's a little weird is this giant ... thing that's going on, we could probably do that a little better but this works because we want to work off this current file, it seems a little weird though, so maybe there's a better way to do it, and if you have a better idea submit a GitHub issue, I would love to see it. That is it, we've added the generator pretty simply, we didn't even know what we were doing at the beginning of this episode, so that's cool, so I've just refreshed that page, and I bet if we look at these views, that we render we see simple calendar's month calendar rendered two times, and that means that it's using the local version inside our rails app, and I bet if we remove app/views/simple_calendar and we refresh this page again, that it should be rendering the views from inside the gem, and it is. You can see the full long path name that it rendered, which means that we're successfully allowing you to override those inside your rails app, and we've got all that functionality that we were looking for and we're pretty much done, this is definitely worth adding to Git, so we'll add the generators, git add lib, and then make sure that we got the generator correctly, git commit -m "Add views generator for customizing calendar views" Let's push this up to GitHub, and we should be pretty much done with the changes that we wanted to make to this gem. There's a few other things that we wanted to do of course that are like multi-day events, but this is at a state pretty much with the simple calendar gem that we could release this if we wanted. I think it's worth walking through a bunch of things tomorrow and just making sure that it's ready to go, but I wouldn't be opposed to releasing this up on rubygems tomorrow if that is deemed.

It's complete enough, maybe we should add some tests, that would be a good idea, add some tests before we release that, but we've done a giant refactoring and we have a much more manageable and customizable gem, so I'm pretty excited about that, we're making really good progress. That's it for today and I will talk to you tomorrow. Peace

Transcript written by Miguel


Subscribe to the newsletter

Join 31,353+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.