rails + angularjs + bower-rails + heroku

Difficulty: Punch a hole in the wall

Yes, that’s what you’ll most likely want to do prior to actually getting this to work. It’s challenging to get this to work.

So it’s funny. I started this post a week ago. And Guess what. I never finished the post at that time. And now I want to punch myself cuz I have to re-learn EVERYTHING. What a shame right?

Disclaimer

This tutorial is going to be impossible to follow. It probably won’t help you, but just frustrate your more. You should definitely start looking at other tutorials. Here are some other tutorials.

  1. Angular with Rails Part 1 (this one is good until the end. The code formatting is incorrect and that messes with coffee)

So what makes getting this combination so difficult to get going? There are MANY waays to skin this cat. It’s hard to combine ideas from multiple tutorials because one tutorial may negate what you’ve done in the other because they use a different approach which looks SIMILAR. You can quickly find yourself punching code in without understanding what’s going on and that’s when shit goes way wrong.

Why do all this extra work of AngularJS, Bower? Rails provides me with javascript files.

Javascript gets unwieldily very fast with Rails.

My story: Once I built a project. And I just started tossing Javascript in various javascript files that rails created for me. I was like oh great, rails has created these Javascript files just for me! And if I want to write javascript for that specific controller, I just toss it in the javascript file labeled specifically for that controller.

WRONG. Code placed into that folder loads everywhere on every page. All of a sudden I’ve got javascript errors in places I would have never expected. It got so bad, I couldn’t even continue to develop the project. So I gave up. I fucked it up so badly I literally had to restart the project from scratch.

Very similar to me of trying to deploy Ghost on Heroku for the first time.

Fuck it, let’s get started!

$ rails new rails_angular_bower_heroku_haml_not_working --database=postgresql

Heroku only works with Postgres. That’s why we need: --database=postgresql If you forget that, you’ll be hating yourself later.

Let’s go into the application and create a Rabbit scaffold where we can test.

$ cd railsangularbowerherokuhamlnotworking
$ rails g scaffold Rabbit name:string age:integer on_facebook:boolean

Now let’s create the database. Since postgres isn’t a file based database like sqlite, we have to create the database, then migrate it.

$ rake db:create
$ rake db:migrate

Let’s get rid of the shitty turbolinks Gem.

REMOVE from Gemfile

gem 'turbolinks'

REMOVE from app/assets/javascripts/application.js

//= require turbolinks

Ok, let’s edit our Gemfile and add some of the needed Gems.

gem "angular-rails-templates"
gem "bower-rails"

Now install the gems: bower-rails and angular-rails-templates

$ bundle

Let’s continue to follow the bower-rails github tutorial.

$ rails g bower_rails:initialize json
=>    create  bower.json
=>    create  config/initializers/bower_rails.rb

The bower.json file is where we manage all our dependencies. We want to add our dependencies to the vendor folder. This is something bower-rails will handle correctly IF we put the dependencies in the correct place.

Let’s edit our bower.json file to require AngularJS.

{
  "lib": {
    "name": "bower-rails generated lib assets",
    "dependencies": {
    }
  },
  "vendor": {
    "name": "bower-rails generated vendor assets",
    "dependencies": {
      "angular": "~1.4.7"
    }
  }
}

Your bower.json file should look just like that.

Here is where it becomes unclear on what the fuck to do. We haven’t actually installed anything. So let’s try that.

$ rake bower:install
=> /usr/local/bin/bower install -p 
=> bower angular#~1.4.7            cached git://github.com/angular/bower-angular.git#1.4.7
=> bower angular#~1.4.7          validate 1.4.7 against git://github.com/angular/bower-angular.git#~1.4.7
=> bower angular#~1.4.7           install angular#1.4.7


This is a a bower-rails command and it should look like it installed something. You should see a folder called angular when you run the following command.

$ ls vendor/assets/bower_components/
=> angular
Let’s now create the AngularJS folder structure.
$ mkdir app/assets/javascripts/angular-app
$ cd app/assets/javascripts/angular-app/
$ mkdir templates/ modules/ filters/ directives/ models/ services/ controllers/

That will create a bunch of folders which will contain javascript files, once we get to that… which may be never.

Update app/assets/javascripts/application.js to read

//= require jquery
//= require jquery_ujs
//= require angular
//= require angular-rails-templates 
//= require angular-app/app 
//= require_tree ./angular-app/templates
//= require_tree ./angular-app/modules 
//= require_tree ./angular-app/filters 
//= require_tree ./angular-app/directives 
//= require_tree ./angular-app/models 
//= require_tree ./angular-app/services 
//= require_tree ./angular-app/controllers 

This gets all our new folders required.

Let’s now tell our application it is a AngularApplication by editing app/views/layouts/application.html.erb

<html ng-app>

Now let’s add some stuff to our app/views/rabbits/new.html. to really test whether we got this working or not!

    Name: <input ng-model="name"><br />
    Hello, {{name}}!

Let’s start the application and test it out!

$ rails s

And visit http://localhost:3000/rabbits/new in your browser. Hold your breath… oh… darn… we get an error…

Couldn't find file 'angular-app/app' with type 'application/javascript'

This is a weird error, but we just need to add a file named app.js within app/assets/javascripts/angular-app/.

$ touch app/assets/javascripts/angular-app/app.js

Restart your server and Now it freakin works!!! Time to get TURNT.

Wait, don’t get too excited. We’ve now got to deploy this beast to Heroku.

Deploying to heroku

$ git init
$ git add .
$ git commit -m 'initial commit'
$ heroku create
$ git push heroku master

pray

AND HEROKU REJECTED OUT PUSH. WHAT A DIIIIICK.

But I’ve already gone through the pain of this. Heroku told me… Sprockets::ArgumentError: require_tree argument must be a directory. Basically heroku wants a file within all of our folders, otherwise it doesn’t consider them directories. Trust me, it took me hours to figure this out.

$ cd app/assets/javascripts/angular-app/
$ touch controllers/.keep
$ touch directives/.keep
$ touch filters/.keep
$ touch models/.keep
$ touch modules/.keep
$ touch services/.keep
$ touch templates/.keep
$ git add .
$ git commit -m 'stupid ass error'
$ git push heroku master

pray again. Even though it didn’t work last time, and we prayed. It might have an effect this time. Heroku gods said no. They only have a few responses. No or Yes. Sometimes they give feedback. Basically I’m rambling while this is deploying. FUCK YES IT WORKED.

So they named my heroku app… secure-scrubland-6990 That’s nice of them. So now I must visit: https://secure-scrubland-6990.herokuapp.com/rabbits/new

So excitedly I visited that page, only to reach something went wrong. A 500 error. DON’T WORRY I KNOW EXACTLY WHAT’S WRONG.

Just run this command $ heroku run rake db:migrate

LOL Heroku doesn’t know our DB, so we gotta tell it, migrate dawggg.

And now I can visit: https://secure-scrubland-6990.herokuapp.com/rabbits/new

And when I type in our new field. Angular JS just happens to write whatever I’m writing directly next to it. YEWAS.

You can also visit https://secure-scrubland-6990.herokuapp.com/rabbits/new and see it work.

Adding another Bower Dependency

Now… let’s add another dependency. Like for fun. I want to add D3.

bower.json should now read

{
  "lib": {
    "name": "bower-rails generated lib assets",
    "dependencies": {
    }
  },
  "vendor": {
    "name": "bower-rails generated vendor assets",
    "dependencies": {
      "angular": "~1.4.7",
      "d3": "~3.5.6"
    }
  }
}

install the files for the new dependency

rake bower:install

tell rails asset pipeline about our new dependency by adding this to app/assets/javascripts/application.js

//= require d3

Add this to app/views/rabbits/new.html.erb

<script>

d3.select('body')
  .append('h1')
  .text('Hello World!');
</script>

And it works.

Post Content