Discourse as Your First Rails App

Shawn Holmes April 9, 2013

If you’re a developer, but have never touched Ruby on Rails, we understand how you feel. We were there once! Sometimes diving into a new language and codebase can make you feel like this:

Discourse has a great, supportive community on GitHub and meta.discourse, and we’re here to help. This is our first guide to setting up a local Ruby on Rails environment, custom tailored to begin dabbling in Discourse.

Step 1: VirtualBox

For those who don’t do it on a regular basis, It can be intimidating to set up a *nix flavored environment. For us, the path of least resistance lies in the safety of a Virtual Machine, a doorway into an entirely different operating system. We recommend VirtualBox. It’s free, open source, and runs on Windows, Linux, Mac and Solaris. Download a copy from the VirtualBox site here:

As of this writing, 4.3.26 is the latest and works for us. After you’ve downloaded and installed it, there are a couple of things to know which will help your VM’s performance.

  1. Use a Solid State Drive (SSD). A VM emulates an entire system. There’s a performance cost to this emulation, a little in CPU and memory, but mostly in disk I/O. You can get big improvements in VM speeds by moving from traditional disks to a solid state drive.

  2. Have two drives. If you install VirtualBox to run from your primary drive, and you run a VM that also resides on that primary drive, they’re going to fight for hard drive resources. The more your primary disk is tied up, contending between the management of resources necessary to run VirtualBox and the emulated resources inside the VM, the slower your performance is going to be. If you can, try keeping your working directory (of Discourse and the VM) off of the primary disk. In a perfect world, your secondary disk would also be a SSD!

  3. Increase the VM memory. The VM image we set up defaults to 1 GB of memory, which makes it friendly to run on 4 GB machines. But this is the practical minimum — performance will be a lot better if you can ramp the VM memory up to 2 GB or even 4 GB. To do so, change your system’s DISCOURSE_VM_MEM environment variable to the desired amount of memory.

Also, we recommend a development machine with about 8 GB of physical memory. VMs are hungry and eat ram like Hippos eat marbles.

Step 2: Vagrant

With VirtualBox installed, it’s now time to bring a VM to life. Discourse maintains all the information necessary to wire up a VM within the Discourse codebase itself!

It does this through the magic of Vagrant, another free open-source tool which is used to both package and initialize a VM with all the necessary configurations in place. Thanks to Vagrant, there’s no need to figure out if you have the correct version of Ruby, or if Rails is up-to-date, or even how to install nginx, thin, or any of the other bits and pieces that make up Discourse.

It’s all in Vagrant, stored within the Vagrantfile, and comes up with with the ease of a single command line. For the purposes of working with Discourse, you’ll need Vagrant 1.7.2 or higher. Download it from the Vagrant download page:

Install should be self-explanatory. Go ahead and do that now. We’ll wait.

Step 3: Git

Source control is vital, not only as a means of tracking changes and protecting yourself from change, but also perhaps more importantly as a way to make collaboration and contribution easy.

First timers to Git can find it is a bit intimidating, even if you have previous experience with Subversion et al. If you want the easiest experience to start, we recommend the official GitHub clients:

Once installed, head to the Discourse repository on GitHub and click the Clone in Windows / Mac button:

This will pull a copy of the repo down to your machine, and your GitHub tool will load it into its local repositories. Clicking on the “repositories” section on the left, under “local” will take you to all your cloned repos. To peek inside the repo, click the blue arrow, just to the right of the thumbtack:

The complexities of Git will need an entirely new blog post, so we’ll leave that to the experts. For now, three tips:

  1. If possible, set up your working folder on a disk other than where you installed VirtualBox. Do this through the tools option along the top of the GitHub application (look for the gear icon in the screenshot above).

  2. Hover over the repo to see the current working folder for the project:

  3. To open a command shell in the project, right click the project and select open a shell here, or use the project tools (gear icon) menu again.

Keep those last two points in mind, because you’ll need them for the next section!

Now that you have cloned the Discourse project locally, you also have our official Vagrant configuration along with it. This will drive the VM in VirtualBox. Let’s put all the pieces of this puzzle together, shall we?

Step 4: Running the VM and Connecting to It

Using the GitHub for Windows or Mac tools (gear) menu for the project, select open a shell here.

This will give you a command prompt at the current project folder. From there, type:

vagrant up

This will kick the VM into motion. Vagrant will connect to the official Discourse site, download the VM image we’ve prepared (note: this may take a while), extract it, and enable all the subsystems necessary to bring the environment to life. VirtualBox may prompt you a few times, so go ahead and accept its requests.

Once the VM is up, you’ll be back at the command prompt.

Now, it’s time to connect to the VM and start up the Rails server. From the shell you already have open in the project folder, type:

vagrant ssh

Once inside, a few more commands is all it will take. Change to the vagrant directory:

cd /vagrant

Now it’s time to interact with Ruby on Rails. Invoke the Rails installer, like so:

bundle install

Next, tell Ruby on Rails to migrate the development database schema into your local repo. We do this via rake, which is Ruby’s version of make, boasting Ant-like features.

bundle exec rake db:migrate

At long last, it’s time to bring up the Rails server, ready to accept HTTP requests.

bundle exec rails s -b

Our VM config causes this Rails server to begin listening for requests on port 4000. So once the server is up, open up a web browser on your local workstation and navigate to http://localhost:4000

Voila! As you can see in the screenshot above, Discourse is indeed running locally off of port 4000, and in the background, you can see the guts of Discourse working away within the SSH client that you used to launch the server.

The initial request may take a while as Discourse begins to initialize its subsystems and start the caching processes; first page loads of 5 to 10 seconds are not uncommon. However, if you’re seeing page load times well beyond this, let us know what your PC configuration is. The Discourse community is actively looking for tweaks and improvements for better VM performance.

Step 5: Shutting Down

When you’re done for the day, Ctrl+C will kill the Rails server, exiting you back to the command prompt from within the VM. To finish up, type:

vagrant halt

This will exit your SSH session, then end the VM and free up its resources.

Congratulations! You now have a working copy of Discourse, ready for you to hack away at any time, and a complete Ruby on Rails environment to facilitate said hacking.

Now go forth and hack — and please consider contributing any cool stuff you build back to the project as pull requests!

Notable Replies

  1. sam says:

    I have seen some twittering by @robconery that I would like to respond to here as opposed to on twitter.

    Getting started with Rails on Windows is hell, there, I said it. People often have this delusion that there is this magical Ruby installer you can install, it installs Ruby, you can use that develop Rails.

    The reality is that Ruby, as used by most Rails apps is full of unixism, performance of Ruby MRI (the default Ruby) on Windows is abysmal, Rails load times are hellish, sooner or later (more likely sooner) you are going to hit gems that simply do not work properly on Windows.

    So ... if you are on Windows (Disclaimer: my primary Dev machine is Windows 8) and would like to play with Rails you are must install a Linux VM.

    Getting a VM from 0, to ready to rock-and-roll with Rails is a tedious task. You need to install Ruby (preferably rbenv or rvm). You need to configure a database. You need to install a whole bunch of weird and wonderful packages you never knew you needed, like libreadline or libyaml.

    The article presents a very simple way to get a bootstrapped VM ready for Rails and Discourse development. It takes care of a bunch of things for you that you probably never even knew you needed, including GC tuning.

    You can use that VM to develop other Rails apps if you wish, its bootstrapped and ready to go. This series of tweets is merely criticising the title, the beef of the article is about giving a simple way for Windows users to get started with Discourse.

    In response to some of the particular points:

    Discourse is highly tuned for performance

    Hell yeah, and we are playing nice with the community helping tune Rails with stuff we find.

    I have personally built flame graph support for MiniProfiler, we are finding all sorts of wonderful things and making sure we share all this love with the community.

    There is this complete misconception out there that Discourse does not use Active Record idiomatically, the reality is that the majority of Discourse is idiomatic Active Record and idiomatic well tested Rails with the odd performance exceptions. Sure, you can point your finger at a few exceptions, but look through all the code, not only at the exceptions.

    Discourse uses pretty idiomatic Active Model Serializers for persistence, we made a few contributions to help turbo boost them.

    Our test suite contains over 2000 tests. Our code base has been heavily scrutinized due to our high profile and heavily refactored since launch.

    uses a heavy Single-Page App approach

    Like it or hate it, Discourse is an Ember app, we work with @tomdale @wycats and team to make sure our Ember code is as idiomatic as possible. A lot of ground has shifted under our feet in the last year, keeping up with best practices can be hard. Nonetheless, we are not afraid of making big changes, like shifting our code from CoffeeScript to JavaScript or doing major refactoring so the code flows better. We are totally open to contributions from the community.

    If you don't want to touch the Ember bits and still want to hack on Discourse, there is plenty to do.

    Which brings me to my final points:

    The sentiment of the tweets, is move along, nothing to see here, if you are new to Rails avoid at all costs. I think that sentiment is completely wrong.

    If you are a Windows dev and want to get started hacking on Discourse, this is the easiest way for you to get going.

    • It gives you a VM where you can hack on the Discourse CSS and get live reloads as you are hacking, allowing you to easily contribute style changes to us.

    • Plenty of areas of Discourse could do with help and don't require extensive Rails knowledge, like building new oneboxes

    • If you are a JavaScript dev there is plenty to hack on that does not involve even looking at Rails code.

    • If you would like to get started with some Rails bits, you could look at amending models, controllers, or libraries.

    • As an added advantage, you will have a VM that you can use for hacking on many other Rails apps.

    • Its still early days, but we intent to have a very simple mechanism of building plugins, and this will be an excellent bootstrap for it.

    • See also:

    Yes, Discourse is huge, I would probably not learn how to program or how to build Rails apps just by reading Discourse source code. That was never the intention. There is plenty to learn from the code, there is plenty to hack on for a wide variety of backgrounds. Looking at our code is not going to make you a bad Ember or Rails developer. Reading lots on lots of different bits of code is the way you become a better developer.

    And, as always this vagrant image is simply a service to the community. Make it easier for Windows developers to get started hacking on Discourse. As an added bonus they can use the image to hack on any Rails project.

  2. Here is a quick and dirty translation of Getting Started for Debian/Ubuntu users if you want to toss it in a script or something:

    1. sudo apt-get install git virtualbox nfs-common nfs-kernel-server
    2. wget
    3. sudo dpkg -i vagrant_x86_64.deb
    4. Open a terminal
    5. Clone the project: git clone
    6. Enter the project directory: cd discourse

    Then continue on with the rest of the instructions ... (I'm getting an error with the NFS client thing, but that should work, I'm investigating that and will update this when I find the cause.)

  3. Using the shared folder /vagrant will provide really low performance.

    If you want decent performance, you will need to do the following:

    # create an alias to synchronize the code from the shared folder to a local folder
    alias sin="rsync -a --delete /vagrant ~"
    # actually synchronize (can take a minute for the first run)
    # switch to the local folder
    cd ~/vagrant
    # standard procedure to update, migrate and launch the application
    bundle install
    bundle exec rake db:migrate
    bundle exec rails s

    Enjoy :wink:

  4. Hi! First of all, thanks for the guide which is a great help to ROR newbies like myself.

    I have followed the steps provided in the guide to a T. There are no problems with setting up the VM, installing the bundles and getting everything up and running. However, once the server is up, and I open localhost:4000, it is taking an eternity to load. Much longer than the "5 or 10 seconds" mentioned in the Discourse guide. It took upwards of 3 to 5 minutes for my first-time load. Is this expected given my system config provided below?

    I've run the tests as mentioned in the Discourse Troubleshooting guide and all of them pass without any issues. I get zero failures. It should be noted that everything I am doing is right off the Master branch.

    My system config is as follows:

    CPU: Intel Core i5 760 2.8 GHz Quad Core
    RAM: Transcend 12 GB RAM
    Primary HDD: 128 GB SSD (This is where Windows 8.1 is installed)
    Secondary HDD: 250 GB 7200 RPM HDD (This is where all my VMs are stored. Most importantly, this is where "only" my VMs are stored. Unfortunately, not an SSD at this point, working on that.)
    Virtualbox version: 4.2.10
    Vagrant version: 1.2.2
    RAM allocated to Ubuntu VM: 4GB

    This is what I get the first time I open up Discourse: LINK

    And this is the second time, obviously faster: LINK

    I am not sure whether I am doing something incorrectly, but I just wanted to bring this to your attention.

  5. Oh my. You're right, they're not really intended for dev... @npruehs are you sure you're running everything from inside the VM?

  6. I hope my question isn't silly in some way but I'm having trouble following this how-to. When I attempt bundle exec rake db:migrate, I get this error:

    rake aborted!
    NameError: uninitialized constant SiteSettings::DbProvider::RailsMultisite
    /vagrant/lib/site_settings/db_provider.rb:52:in `current_site'
    /vagrant/lib/site_setting_extension.rb:44:in `current'
    /vagrant/lib/site_setting_extension.rb:96:in `block in setting'
    /vagrant/lib/site_setting_extension.rb:93:in `synchronize'
    /vagrant/lib/site_setting_extension.rb:93:in `setting'
    /vagrant/lib/site_setting_extension.rb:151:in `client_setting'
    /vagrant/app/models/site_setting.rb:18:in `block in load_settings'
    /vagrant/lib/site_settings/yaml_loader.rb:29:in `block (2 levels) in load'
    /vagrant/lib/site_settings/yaml_loader.rb:20:in `each'
    /vagrant/lib/site_settings/yaml_loader.rb:20:in `block in load'
    /vagrant/lib/site_settings/yaml_loader.rb:19:in `each_key'
    /vagrant/lib/site_settings/yaml_loader.rb:19:in `load'
    /vagrant/app/models/site_setting.rb:16:in `load_settings'
    /vagrant/app/models/site_setting.rb:25:in `<class:SiteSetting>'
    /vagrant/app/models/site_setting.rb:4:in `<top (required)>'
    /vagrant/config/initializers/04-message_bus.rb:39:in `<top (required)>'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/engine.rb:652:in `block in load_config_initializer'
    /var/lib/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/notifications.rb:166:in `instrument'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/engine.rb:651:in `load_config_initializer'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/engine.rb:616:in `block (2 levels) in <class:Engine>'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/engine.rb:615:in `each'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/engine.rb:615:in `block in <class:Engine>'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:30:in `instance_exec'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:30:in `run'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:55:in `block in run_initializers'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:44:in `each'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:44:in `tsort_each_child'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/initializable.rb:54:in `run_initializers'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/application.rb:352:in `initialize!'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/railtie.rb:194:in `public_send'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/railtie.rb:194:in `method_missing'
    /vagrant/config/environment.rb:5:in `<top (required)>'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/application.rb:328:in `require_environment!'
    /var/lib/gems/2.2.0/gems/railties-4.2.4/lib/rails/application.rb:457:in `block in run_tasks_blocks'
    Tasks: TOP => db:migrate => environment
    (See full trace by running task with --trace)

    Can anyone help me?

Continue the discussion

120 more replies