IntelliJ has a feature called modules: “a functional unit which you can compile, run, test and debug independently.”
A module in IntelliJ is a top-level view on a part of a codebase. IntelliJ is for Java, which is why I do not typically use it. I use Rubymine – no similar functionality exists here… but a way around that!
It may have been true at some point that these kind of modules were not something that Rails offered, but they have been around for quite a while: Engines!
Engines are typically seen as a way to package a Rails app that can be reused and configured in the context of other Rails apps. However, many big Rails projects can benefit from engines and their ability to structure a large codebase into smaller, more independent parts. Namespacing within one Rails app can achieve a similar effect, but engines take it to the next level: all the code, including views, javascript, and even rake tasks and migrations can be separated consistently. Now, if the apps were totally separate, several independent Rails apps might be the right solution, but if those are tied together by the same database, one might do more harm then good when ripping that code apart…
The Problem
Imagine a Rails project with the following folder structure:
rails_app/
app/
...
engines/
custom_engine1/
custom_engine2/
...
The engines are somewhat hidden away, two levels deep in the folder structure. Also, running specs for engines in these sub-folders won’t work from Rubymine, because the paths it tries to use are wrong.
Whether you are actually working with engines or just want to see multiple root folders in Rubymine at once, here is how to do it.
Make modules work in Rubymine
1) You can get modules to work in Rubymine by opening your Rails project in IntelliJ: Cmd + ;
opens the project structure dialog, select Modules
from the list on the left and create a new module with the +
button. Or, you can simply add a few files to your project…
2) The .idea folder in the root of your project holds the Rubymine configuration files. Edit modules.xml
and add a module
line for every module you would like to create:
<!-- ROOT/.idea/modules.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/custom_engine1/module1.iml" filepath="$PROJECT_DIR$/custom_engine1/custom_engine1.iml" />
<module fileurl="file://$PROJECT_DIR$/custom_engine2/module2.iml" filepath="$PROJECT_DIR$/custom_engine2/custom_engine2.iml" />
</modules>
</component>
</project>
In the root folder of every module create a .iml
file with the name of that module like so:
<!-- ROOT/engines/custom_engine1/custom_engine1.iml -->
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUBY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Voila: The next time you open the project folder in Rubymine, the custom_engine folders show up as top-level entries in the projects file list!
Here is the gist: https://gist.github.com/1764127
This worked for me with Rubymine 3.2.4 and IntelliJ IDEA 11 CE.
Edit March 14: make sure that all module names are distinct and no module names are substrings of other module names. This confuses RubyMine and can prevent specs from running successfully.
About the Author