Subdomains, multitenancy, and custom selects with Rails

Nerd Notes
09.03.14

For those of you who are interested, OddJob U was made on Ruby on Rails, using pgSQL. We're hosting this app, and most likely all of our apps, on Heroku. They have a free tier for apps that can be scaled when needed, and they save us a lot of money and time.

The Backend

On the backend, I used the actsastenant gem in order to separate each school and subdomain. We wanted to incorporate multi-tenancy to prevent the overlap of data from college to college. To use this in your app, do the following:

Add actsastenant to your gem file.

  gem 'acts_as_tenant'

In your application controller, use the following before_filter:

  def set_subdomain
    @college = College.find_by(subdomain: request.subdomain)
    if !@college && request.subdomain != 'www'
        redirect_to home_root_url(subdomain: 'www')
    end
  end

This will separate the different domains, but still allow you operate on the www subdomain (and any others you choose).

In your routes.rb file, include the following

  class SubdomainPresent
    def self.matches?(request)
        request.subdomain.present? && request.subdomain != "www"
    end
  end

  class SubdomainBlank
    def self.matches?(request)
        request.subdomain.blank? || request.subdomain == 'www'
    end
  end

  # and in the routes part
  Rails.application.routes.draw do
    constraints(SubdomainBlank) do
        root 'welcome#index', as: :home_root
    end
    constraints(SubdomainPresent) do
        resources :posts
        # other stuff that you want...
    end
  end

This helps the application controller and actually routes your app to the right place.

Also be sure to set up the correct actsastenant association in the appropriate model.  For us it was the post.rb, and we simply wrote:

  acts_as_tenant(:college)

Finally, I used rails_admin to help build the admin panel.  I'll be using this often, and it helps a lot in creating quick admin panels for your apps.  

To make it work with actsastenant, add this line to your application.rb:

  def rails_admin_tenant
      ActsAsTenant.current_tenant = nil if self.is_a? RailsAdmin::MainController
  end

And make sure to keep it in your www domain only (routes.rb)

  constraints(SubdomainBlank) do
    mount RailsAdmin::Engine => '/nottellingyouoururl', as: 'rails_admin'
    #other stuff
  end

One cool feature we found when setting the custom banner colors and images, was the color picker in rails admin.   Just add the following to a [config/initializers/rails_admin.rb]

  config.model College do
    configure :banner_color, :color
    configure :menu_color, :color
    configure :tab_color, :color
    configure :pin_color, :color
    configure :jobs_color, :color
    configure :tab_hover_color, :color
  end

And that's some of the main stuff used on the back end! Feel free to ask questions regarding anything above. I also want to share a few other gems I used to give credit to the makers and also show some resources for your future projects:

  • Searchkick: Used for search, and can combine well with the filters we used (sorting by category and off/on campus)
  • Seedbank with Faker: Helps populate development database with fake data. Really helped quicken the process of front-end development and finding edge cases.

The Front End

Now on to the design and the stuff people actually see.  I won't be going into as much depth, but will touch on a couple things.  If you see anything on the site that you are interested in figuring out how we did, once again let us know!

For this project, we used SASS, and the add-ons Bourbon & Neat - both made by the excellent firm Thoughtbot.

These help set up a responsive grid.  If you would like to use these tools, but not go fully responsive, set a max with in your SASS/CSS file.

  body {
      max-width: 1028px;
  }

Another interesting front end feature on the site is the home page.  For the drop down menu, we wanted to completely style the product.  We started out with the fancy select plugin.  We then completely customized it to meet our needs.  It took a bit of hacking, but we think it looks pretty cool.  If you use this plugin, to prevent it from having an overflow issue when it is close to the bottom of the page, set a max-height when there are enough choices and scroll will be enabled.

We did it like this:

  if (numOfOptions > 3) {
      $('div.fancy-select ul.options').css('height', '150px');
  }

I may create a custom plugin sometime during this challenge or after to help people create cool and easy to customize select boxes, so stay tuned for that.

Although the coolest feature for me is the subtle mascot on each home page (check out the Blue Devil and the Cal Bear), one thing that could be useful is setting custom school colors for the various objects.  You can do this in any app that you want to customize for a user.

We used the gem gon to bring rails variables to the javascript.  Each college has a set of colors created in the admin panel.  In the application controller, we made a before filter on school pages to find the colors and save them into the javascript.

  def set_color_pallete
    if @college
      gon.colors = {
        banner: @college.banner,
        banner_color: @college.banner_color,
        menu_color: @college.menu_color,
        tab_color: @college.tab_color,
        # etc...
      }
    end
  end

You can also just pass the whole college variable into there.  From there, we would use javascript to change the colors on each page.  For example, the pin color was set using:

    $('.circleP').css('background-color', gon.colors.pin_color);

And that's everything I have to say this week.  I really didn't intend to write much, but got a bit carried away.  For more, follow us on twitter @teammuno.

I'm tired now.