Nepal on Rails

millisami's rants!

Setting Up Rails Engine With Rspec, Guard and Zeus

Update: One gain, you don’t have to cd into the spec/dummy folder. Just run from the same engine’s root files.

I love zeus for testing rails apps because of its speed. Recently I have re-started developing an engine and the default zeus start command is not enough for a rails engine.

So, found this gist and I could setup to run it. Here is the my copy of that gist. Do rename the my_engine with your engine name at line 8.

engine_plan.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
require 'zeus/rails'

ROOT_PATH = File.expand_path(Dir.pwd)
ENV_PATH  = File.expand_path('spec/dummy/config/environment',  ROOT_PATH)
BOOT_PATH = File.expand_path('spec/dummy/config/boot',  ROOT_PATH)
APP_PATH  = File.expand_path('spec/dummy/config/application',  ROOT_PATH)
ENGINE_ROOT = File.expand_path(Dir.pwd)
ENGINE_PATH = File.expand_path('lib/my_engine/engine', ENGINE_ROOT)

class EnginePlan < Zeus::Rails
end

Zeus.plan = EnginePlan.new

And now we need the zeus.json file as well.

zeus.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "command": "ruby -rubygems -r./engine_plan -eZeus.go",

  "plan": {
    "boot": {
      "default_bundle": {
        "development_environment": {
          "prerake": {"rake": []},
          "runner": ["r"],
          "console": ["c"],
          "server": ["s"],
          "generate": ["g"],
          "destroy": ["d"],
          "dbconsole": []
        },
        "test_environment": {
          "test_helper": {"test": ["rspec", "testrb"]}
        }
      }
    }
  }
}

With this setup, now lets run the specs. Install zeus with gem i zeus. In one window, start zeus with zeus start and in another window run the specs zeus rspec spec/file_spec.rb

If your spec pass, you might notice it will run it twice, upper one being green and another failing one. To mitigate this issue, in the spec_helper.rb file, just delete/comment the line require rspec/autorun.

Ahaa!! moment!! Wait, everytime I write/modify the code, I’ve to go to the terminal and run that command zeus rspec spec/file_spec.rb again and again.

You might be yelling, dude we have guard for this. Yeah!! Yeah!! Recently, guard-rspec has added the support for zeus, so lets install it first. Put it in the Gemfile and bundle it.

Gemfile
1
2
3
4
5
group :development do
  gem "guard"
  gem "guard-rspec", require: false
  gem "zeus", require: false
end

Then init the Guardfile

Guardfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
guard :rspec, cmd: 'zeus rspec', keep_failed: true, all_after_pass: true do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  # watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$})          { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

#   # Capybara features specs
#   watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$})     { |m| "spec/features/#{m[1]}_spec.rb" }
end

Now you can run guard either with the bundle exec prefix or just the guard command if you have installed Guard outside the bundle with gem i guard

Happy Engine Testing!

Publishing Cookbook to Chef Community Site

After creating my first errbit cookbook, and publishing it on the chef community site, I’d to do some stretches to publish it.

First, you need to tgz your cookbook and it should have the metadata.json file otherwise the validation fails and the cookbook won’t be published.

So, I am putting it here for me and others:

In your cookbook dir, create a dir .chef with a knife.rb file in it with the following line:

cookbook_path "."

Then issue the command knife cookbook metadata . (Don’t forget the dot) This will generate metadata.json file.

Better to commit it here and push the changes to your git repo.

Now step out 1 dir path from your cookbook folder and do the compressing.

cd ..
tar -czf errbit.tgz --exclude bin --exclude .envrc --exclude .vagrant --exclude .bundle errbit

You might have to change/add the --exclude vars according to your setup.

Now we’ve the errbit.tgz file with the metadata.json file in it which you can upload to the community site at http://community.opscode.com/cookbooks/ne w

When updating the cookbook later, do change the version in metadata.rb file and repeat the same process to publish your cookbook’s changes.

How to Get Facebook Page_id and Access_token to Publish on Its Wall

Its always tricky to post on the wall of the FB Page. It requires PAGE_ID and ACCESS_TOKEN (Not the user’s access token) and so many questions on how to get facebook page id and access token.

The FB Developers webapp way

First create a page by visiting http://www.facebook.com/pages/create.php?ref_ type=sitefooter But this is optional. If you’ve already created the page, the just skip this part. Create a facebook page

  1. Create an App

Create App Dialog

  1. Created App admin page

App Admin Page

  1. Graph API Explorer

Choose the App

  1. Get Access Token

In the Extended Permissions tab, select manage_pages and publish_stream and click Get Access Token Extended
Permissions

  1. Authorize you account

Authorize

  1. Allow Permission

Grant Permission

  1. Copy the blue-highlighted temporary access token

Temporary Access Token

  1. Permanent Access Token

The above temporary access token is also valid. But its limited to 60 days. Its better to have the permanent access token so that it works in the long run, though I forget to updated periodically.

To get this, go the following url replacing the TEMPORARY_ACCCESS_TOKEN value with the temporary access token.

https://graph.facebook.com/me/accounts?access_token=TEMPORARY_ACCCESS_TOKEN

Permanent Access Tokens

Ruby Way

  1. First we need to get the PAGE_ID of the page. To get this, visit https://www.facebook.com/pages/

And on the left sidebar under Pages section, select the page. Page

  1. Copy the Page id from the address bar

Page ID

  1. Here I’m using the fb_graph gem

require ‘rubygems’ require ‘fb_graph’ require ‘pry’ FbGraph.debug!

PAGE_ID = “349835561791721” YOUR_ACCESS_TOKEN = “……”

owner = FbGraph::User.me(USER_ACCESS_TOKEN) pages = owner.accounts

page = pages.detect do |page| page.identifier == PAGE_ID end

binding.pry page

There is the page access_token

Enjoy!!

Invoking Rake Task Within the Rails Console

In some situation, I’d to invoke rake task from the console itself. This makes me do it that with just 3 lines of code right from the rails console.

require rake
MyApp::Application.load_tasks
Rake::Task[the_rake_task].invoke

Rails3 Singleton Resource With Form_for Gotcha

Dealing with the singleton resource was quite a bit tricky:

# config/routes.rb
resource :passion

# form.html.slim
= form_for @passion do |f|

Throws an error:

undefined method `passions_path for #<#<Class:0x0000012d957008>:0x000001347f1ae0>`

So the fix is:

= form_for @passion, url: passion_path do |f|

Use Cases of ActiveSupport Library

While building a Gem or API or any rubyish, the active_support library comes in so handy. So, listing here some usages as a reminder for me (maybe for you too).

  1. https://github.com/gocardless/gocardless-ruby/pull/4/files
  2. Mongoid Indifferent Access
  3. Ruby on Rails3 Tutorial Book Ref
  4. http://rubydoc.info/docs/rails/Hash#except!-instance_method
  5. http://guides.rubyonrails.org/active_support_core_extensions.html

I’ll be updating this list as I find its other use-cases or you can add on the comments and I’ll update this.

Replacing Rvm With Rbenv Using Homebrew

RVM was such a great tool to switch between various rubies and gemsets. But from my last update of the rvm using rvm get head, my shell hangs whenever I change the directory.

So, I thought it is the time to move on with rbenv.

First delete the rvm with the following cmd:

rvm implode

Delete the rvm specific code from your ~/.bashrc or ~/.zshrc or whaterever files related to the shell you’re using.

Then install rbenv and rbenv-gemset via homebrew.

brew update
brew install rbenv rbenv-gemset

Creating a global gemset

echo global > ~/.rbenv-gemsets
gem install bundler
cd project
echo "project-gemset global" > .rbenv-gemsets
bundle install

Whenever you create a gemset and want to share some gems like bundler, install the bundler in global gemset as above and add the global gemset along with the project specific gemset in .rbenv-gemsets file as above.

Milli Conf Picks #1

Well, lately I’ve been busy with the Chef and still on going. I’ll be adding a series of Screencasts about the chef in coming weeks. This post has been taking shape since couple of months ago. I do follow and watch pretty much every ruby/rails conference videos. On the course of watching, not every videos are interesting based upon the Speaker, Slides and the Subject. So, I’ll be adding my picks here that would minimize mine or others time. The videos I’ll be picking and posting in this series will have the criteria of Good speaker, slides and the content as well. At the same time, not offending other speakers and their talks, this will be my personal picks only.

[SOLID Object-Oriented Design. By Sandi

Metz](http://www.confreaks.com/videos/240-goruco2009-solid-object-oriented- design)

[Less, The Path to Better Design. By Sandi

Metz](http://vimeo.com/26330100)

Set Up Jenkins-CI on Ubuntu for Painless Rails3 App CI Testing

Jenkings-CI, formerly known as Hudson before Oracle acquired Sun, can be installed on Ubuntu pretty easily with the apt-get package manager, but getting it working with Ruby on Rails app, Github with rollified Users involves some glitches, so I’m writing them down for posterity. A good documentation on this is still missing.

Jenkins-1

Setting up Users with different permissions and hooking into private Github repos is too tricky. So, this is the post on setting up the Jenkins-CI on Ubuntu with a Githubfied private repository.

Our Goals:

  1. Setup the Jenkins CI
  2. Integrating with Git and Github
  3. Run the test build when changes gets pushed to Github
  4. Run the test build when new branch is pushed to Github
  5. Notify back to the committer(or team members) if the build fails

Installing Jenkins

SSH into your box. It can be a Vagrant box, VMWare, … I’ve used VMWare Fusion for this write up. Then install it with the following commands.

wget -q -O - [http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key](http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key) | sudo apt-key add -
sudo sh -c echo deb [http://pkg.jenkins-ci.org/debian](http://pkg.jenkins-ci.org/debian) binary/ > /etc/apt/sources.list.d/jenkins.list
sudo aptitude update
sudo aptitude install jenkins

Going Headless

Now that Jenkins is installed, we want to get a headless display configured for our browser based tests. First go to Manage Jenkins > Manage Plugins > Available and install the Hudson Xvnc plugin (this works with Jenkins despite its name). Schedule Jenkins to restart to pickup the plugin. Once installed this gives us the ability to start a headless display automatically when we configure our jobs, more on that later.

With Jenkins configured we need to ensure the required software is installed on the server:

$ sudo apt-get install vnc4server

vncserver requires a password to be set before it can be used, this needs to be set before Jenkins can make use of the vncserver. For this we need to switch to the jenkins user and set a password.

$ sudo -Hiu jenkins
$ vncserver
Enter a password, and verify it
$ vncserver -kill :1 # or whichever display the vncserver output mentioned

Screenshot Gotcha

You have to install imagemagick with to see the screenshot or running browser via Xvnc. But its optional.

Creating the first Job build

After installing jenkins and going to [http://the.ip.address:8080](http://the.ip.address:8080), you’ld see the dashboard of Jenkins. You won’t see any Login, Logout or Signup …. links. This is one of the trickiest part and I’ve addressed it below.

But for now, lets create our first Job build.

  1. First click the New Job link
  2. Give a sensible job name. Your project name can be a good fit but it can be anything
  3. Select Build a free-style software project radio button
  4. And OK

Jenkins-2

Configure the Job

After the above step, you’ll be taken to the job configuration form page. But before adding anything, lets add the Github plugin and some Jenkins configuration.

Install the github plugin

Now go to Jenkins > Manage Jenkins > Manage Plugins and install Github Plugin

Restart Jenkins if the Bundler is not picked up

sudo /etc/init.d/jenkins restart

Setting up users with authentication

To restrict the CI system and give access to your Team members to use or see the build logs, first you’ve to create an account.

  1. Go to Manage Jenkins > Configure System
  2. Check the Enable Security checkbox
  3. Under Security Realm, choose Jenkinss own user database
  4. Check the Allow users to sign up checkbox
  5. Under Authorization, choose Project-based Matrix Authorization Strategy
  6. Add first user with the name admin and another with github (Note: the username for Admin access has to be admin) For github named user, just choose the Overall Read only permission. We’ll use this user later with the Github hook.

jenkins-3

Note: The admin and github user that we’ve added in the above step does not create the User. Then you’ve to create a real user with that same name. Ya, I know, its a bit weird with Jenkins UI.

Go to Manage Jenkins > Manage Users > Create User. Create both admin and github users.

Jenkins-5

Lets finish up the Job configuration

Then finally you have to add the user at Project level at `Project > Configure

Enable project-based security`

Jenkins-6

Database Gotcha

After installing the gems, when tried to rake db:migrate, it looks for config/database.yml file and in many projects its not tracked in the repo. So a good way is to checkin config/database.yml.example file into the repository and copy/rename it to config/database.yml file before migrating during the build process.

cp config/database.yml.example config/database.yml

or you can create a executable shell script and put such kind of actions in it and do check-in this file into your repo. Then you can add ./configure in the build step before running the specs.

For a boilerplate rails app

#!/bin/bash -e
rvm use ruby-1.9.3@myapp
cp config/database.yml.example config/database.yml
bundle install --without darwin
bundle exec rake db:migrate
bundle exec rake

For private projects on Github

If the app is public, skip this step.

Before starting your first build, we need to generate the ssh key for the jenkins user and the RSA of Github.com has to be in the /var/lib/jenkins/.ssh/known_hosts file.

So, lets generate the ssh keys for the jenkins user:

ssh-keygen -t rsa

Copy the contents of /var/lib/jenkins/.ssh/id_rsa.pub file and put it in the Github repository Admin page under Deploy keys. For the Millistarter, it will be at github.com/millisami/millistarter/admin/keys

Jenkins-10

Adding github RSA fingerprint in jenkins home (/var/lib/jenkins)

sudo su - jenkins
jenkins@jenkins:~$ git clone git@github.com:<github_username>/repo_name.git
Initialized empty Git repository in /var/lib/jenkins/github_username/.git/
The authenticity of host github.com (207.97.227.239) cant be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added github.com,207.97.227.239 (RSA) to the list of known hosts.
^C (Hit Ctrl + C)
jenkins@jenkins:~$ ls .ssh/
id_rsa  id_rsa.pub  known_hosts
jenkins@jenkins:~$

Create the tmp directory if ignored in .gitignore which is true quite often

mkdir -p tmp/cache tmp/pids tmp/capybara tmp/sass-cache tmp/sessions tmp/sockets

And if your test has to create some directories, just create them too. In my case, I’d to had tmp/media.

mkdir -p tmp/media

Hooking with the Github web-hooks

Now to run the build automagically when new commit or branch gets pushed onto Github, we have to setup the repository.

Got to the hooks page for your repository. e.g. github.com/<username>/<project_name>/admin/hooks

Under AVAILABLE SERVICE HOOKS > Post-Receive URLs, add github:github@your- ci-server.com/github-webhook/.

The githu:github is the user that we’d created earlier.

Jenkins-9

Then we have to verify Jenkins with Github. Go to Manage Jenkins > Configure System and under GitHub Web Hook, add your Github username and password and click the Test Credential button to authorize once with Github.

Jenkins-7

Git Gotcha on your first build

If you see the following error after checking out your repo:

FATAL: Could not apply tag jenkins-project
hudson.plugins.git.GitException: Could not apply tag jenkins-project
....
....
Caused by: hudson.plugins.git.GitException: Error performing command: git tag -a -f -m Jenkins Build #4 jenkins-project
Command "git tag -a -f -m Jenkins Build #4 jenkins-project" returned status code 128:
*** Please tell me who you are.

You have to add the following in the jenkins user home directory:

# /var/lib/jenkins/.gitconfig
[user]
  name = Jenkins-ci
  email = jenkins@localhost

Setting up the email to notify if the build fails

Go to Manage Jenkins > Configure System and add the SMTP credentials.

Jenkins-8

Final Configuration Assertion

Since the post is TL;DR, here are the 2 screenshots of Jenkins Config and Project Config. Your configuration should resemble this.

Jenkins System Config

Project Config

Bonus(es) and Gotcha(s)

Gotcha with OutBound error

Sometimes we get this error MoveTargetOutOfBoundsError. This is caused if the window size is less than the expected one. At least I think so, not confident. To fix this error, in Manage Jenkins > Configure System > Xvnc Command line put this sh -c "USER=jenkins HOME=/var/lib/jenkins vncserver :10 -geometry 1440x900 -depth 16". I’d to install FluxBox with sudo apt-get install fluxbox. And had to downgrade the Firefox down to 3.x from 8.x.

Adding the code coverage metrics

Install the Ruby metrics plugin plugin, to actually display the graphs of your code coverage.

A project called simplecov, that seems to work really well, but the output format isn’t what jenkins expects. simplecov-rcov, its just a formatter for simplecov, that generate rcov style reports. So lets add this to our spec/spec_helper.rb

require simplecov
require simplecov-rcov
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter

SimpleCov.start rails if ENV["COVERAGE"]

Bonus: Watch your acceptance test run in real graphical window

Download the VNC Viewer viewer for Mac. If you’re on other OS, you can find it by googling around.

Open up a new connection and provide the address and its port.

You can find the port its running on with the cmd:

sudo netstat -tulpn

...
tcp        0      0 0.0.0.0:5910            0.0.0.0:*               LISTEN      3319/Xvnc4
...

References

Imagemagick Installation Pain on MacOS via Homebrew

I often stumble upon the pain of installing imagemagick via homebrew on MacOS for the new trainees on their iMacs.

Just as a note-to-myself:

brew remove imagemagick
rm -rf `brew --cache imagemagick`
brew install -f imagemagick --disable-openmp