When working with one or more modular applications, your coding workflow changes quite a bit. Modularity gives you some advantages, but also comes with some annoying inconveniences.
When working on a modular application, you will essentially be working with two “versions” of the same application. We will explain what we mean, and the theory, by using BlastCRM as our example.
Our current BlastCRM application is the development version. It contains the source code of each engine, and you will need to put the source code of any new module in the
engines/engine_name folder. This is the copy (i.e. version) you’ll work with when you want to add new features. For example, if we change something in the
Core module, we will commit our changes and push the
Core module from this application. Once the code is pushed, we will be able to generate a gem.
With this new gem pushed to a gem server, we will switch to the production application. If you don’t have one yet, you just need to pull the code from the development version. Then, you’ll have to delete the engines folder, update the
Gemfile to use the gems instead of the local folders, and run
bundle install. This way you will have a clean production application that you can push to a new repository.
Here are the main points to remember about development vs production applications:
Git is an amazing tool to keep your source code versioned and work with other people. If you want your work on a modular application to be as smooth as possible, you need to have your engines’ source code versioned. Using
Git (or any
VCS) will allow you to easily work on your modules with your colleagues, and safely add new features by using branches.
But what’s the best approach? Could we just version the parent application with the source code of the modules? That’s one solution, but probably not the best one.
Versioning your parent application is, of course, recommended, but without the modules inside. If you use
git init .) inside each engine, they won’t be versioned with the parent application. You will have to push the parent application and each module to their own repository, but it will give you a log for each module instead of a confusing log for the parent application that contains changes for your engines.
GitHub is a great platform to store your source code. As long as you’re doing open-source projects, everything will be free. If you need private repositories however, it might not be the optimal solution. Private repositories are free only for up to 3 contributors, and you will not have use of the wiki. If you are a small company, and have your own wiki (like DokuWiki) and project management tool, then you’re good to go. If you are a larger company, then the costs can mount up.
Bitbucket is another alternative that charges on a per user basis, and it is free for teams with up to 5 users. Thereafter, the costs start to mount up.
If you have access to any kind of server, you can configure your own git repositories. It won’t cost you anything except for the server price. You can even install some web applications to access Bitbucket/GitHub-like interfaces. If you’re looking for this kind of thing, check out Digital Ocean + Gitolite.
Branches are an awesome feature of
Git that makes working on different features at the same time much easier. Working on modules is not much different than working on a regular Rails application. You want to create a new branch for a module anytime you have to change something. The code should only be merged into
master once it has been tested and is ready to go live.
When you’re working on massive changes to your modular application, we recommend creating a new branch on all your engines and on the parent application with the same name. It is, then, easy to know what you’re working on and branches can be logically merged on each module.
We recommend following the good practices, described at semver.org, to version your modules. In fact, it is a good idea to do this for all your applications. Here is the official summary, but you should definitely take a look at the website.
Given a version number MAJOR.MINOR.PATCH, increment the:
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
When you want to test a packaged module, you should add the branch name to the version number:
1.0.0 will become
1.0.0.branch_name, and should mainly be used to test gems in a staging environment.
Have you ever heard the saying “Eating your own dog food”? If you don’t know it, it means using the tools you create to ensure their quality and capabilities.
Let’s say you’re working on a CMS, like WordPress. Obviously, you want to write it in Ruby. One of the most interesting features of WordPress is how extendable it is. You can easily create a plugin by hooking into WordPress. Of course, you want your CMS to be as famous as WordPress, so having a plugin-ready application is a big plus. With everything you’ve learned in this book, you now have two choices:
You could create a regular Ruby on Rails application. You would then need to start thinking about how people could extend your application. Basically, you’re not “eating your own dog food” because you won’t be using this extension system yourself. And everybody loves dog food!
The other option is to build a modular application the way this book showed you. You’re making your application extendable for yourself, which helps you detect flaws and fix them before you let other people create plugins. You could create the
Core as a very basic system, and create your own modules to add more features like comments, tags, etc. You could even make it in a way that allows people to disable some features easily, by not loading the engines! Next time you’re building an application that has to be extendable, think about it… modularity might be the way to go.