Pilanites

Everything about web apps

Setting Up a Rakefile for TDD

| Comments

This year I attended RubyConf India which was extremely awesome to say the least. I interacted with great programmers and got to learn many new techniques to get most out of this spectacular programming language.

One of my favourite takeaway from Conference was Test Driven Development (TDD), which was showcased by Jim Weirich, creator of Rake. You can take a look at the keynote in this video.

If you notice, Jim mentions that he had setup Rakefile beforehand in interest of time. Allow me to show you how to do it yourself.

Note: I am showing how to setup a Rakefile for test/unit and not for rspec. I’ll cover that someday later.

Open your terminal and cd to the directory where you want to keep your Rakefile. Now, run

$ touch Rakefile

and open the file created. touch creates an empty file for us. Let’s fill it up.

First thing our rake file needs to do is add current directory to ruby’s path so we can use require in place of require_relative.

$: << File.dirname(File.absolute_path(__FILE__))

The $: is global variable in ruby for path directories. So, this line basically adds the directory of current file to path. Of course, this is valid only while the program is running and is not a permanent change.

Next, we need to add test tasks so we can run the command rake test and it automatically runs all the tests for us.

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
  t.libs << "."
  t.test_files = FileList["test/test*.rb"]
  t.verbose = true
end

This makes available the rake test command. One thing you should understand is that our rake test command will look for tests in the test folder. Also, the name of our tests files should start with the word test and end with .rb. We let rake know all these by t.test_files = FileList["test/test*.rb"] statement.

Try running rake at this point. You’ll probably get something like

rake aborted!
Don't know how to build task 'default'

(See full trace by running task with --trace)

This is because right now, we have defined only the rake test command. Running rake invokes the command default command. We can easily set this command to something else. To set it to the test command, just add

task default: :test

at the end of our Rakefile and try running rake once again. No errors this time!

That’s it for setting up our Rakefile for TDD. You can start writing tests in test folder and follow the Red-Green cycle till your hearts content.

Let me know your thoughts or questions in the comments below!

Scheduling Jobs Using Cron in Rails 4

| Comments

After deploying an Application, I have to at times do repetitive things like running a rake job, mailing me the log file, clearing the logs, sending newsletter every friday, etc. These are basically some commands I have to run on a regular basis. Running them manually for sometime is great as it allows us to iron out all the errors, but after it stabilizes, there is no reason for us to be doing it manually again and again.

What we need is a way to automate these tasks, which needs to be triggered at specific amounts of time. The most common way of doing this is to use cron, which is available on most UNIX-based (Linux, Mac for example) systems.

If you are a Unix expert, you might have used cron by editing cron files. To edit them, we simply run the command

$ crontab -e

and write the commands in the file that opens. Syntax is a bit tricky but main problem occurs when you start deploying to multiple servers. You would need to write cron file on every server again and update everywhere when necessary.

Enter, whenever ruby gem! It’s the perfect solution for Rails based applications where you need to use cron.

For example, if I want to run a rake task which sends mail every monday at 7:30 AM, I’ll need to write

every :monday, :at => "7:30 am" do
  rake "send_mail:newsletter"
end

This looks so much better than the cron commands, it scores high on readability points and is easier to remember and change.

For instructions on installation and general usage, you won’t find any better resource than project’s github homepage or the brilliant railscast.

The thing I want to discuss are the issues I faced when my development environment was windows and deployment, Ubuntu!

The very first thing you need to do is set your output to a log file. I had put my output in log/cron.log under my Rails directory.

To do this, write

set :output, 'log/cron.log'

in config/schedule.rb file. This way, all the output from Cron tasks will be shown in log/cron.log file.

Now, the very first problem I faced was it couldn’t find rails.exe in bin/bash. I tried searching on the internet but couldn’t find it. Later, I realized that .exe extension works in windows and not in Ubuntu.

To solve this problem, I opened the file bin/rails and saw

#!/usr/bin/env ruby.exe

written on the very first line there. I immediately removed the .exe extension, commited the repo there and the problem was solved.

By the way, to run open rails console in some other environment, like production, you’d need to write RAILS_ENV=production rails c to make it work. Somehow, rails c RAILS_ENV=production doesn’t work.

At this point, everything was working properly until I deployed my application again. This time, the cron output gave errors about how the rails file was not executable. I later realized that this may be because when I do a git pull, the files in bin folder become read-write and not executable.

This is easy! We just need to do chmod +x bin/rails to make it work. Unfortunately, this wasn’t enough as I forgot to do this every time I pulled from my repo onto the server.

Thus, I added a command type cron job. I wrote in my config/schedule.rb file

command "chmod +x path/to/app/root/bin/rails"

And had it run at 6 in the morning so my jobs, scheduled for 8 AM, 10 AM and 12 AM work without a glitch!

Yup, scheduling jobs is that easy.

Don’t forget to write whenever --update-crontab aap-name to write to cron file. Add it to your capistrano’s after deploy. You can also add chmod +x execution to capistrano’s after deploy. Comment out how you used it.

Also, do let me know if you’ve been able to deploy to your VPS while developing on Windows and using capistrano to deploy.

Deploying Rails 4 to VPS and Fixing Some Problems

| Comments

So, Rails 4 release candidate 1 has been released and I wanted to get a feel of how different things were in it. So, I made a small trivial app to get the feel of changes with which I have to deal with. There weren’t many problems which I faced in the app making process, just watch these two fantastic episodes to get a general overview of changes in Rails 4. The most difficult part was the production environment on which I ran my app. I had a VPS with me and thought of deploying to that VPS by creating the environment right up from scratch. Creating the environment was easy. These are the steps I followed.
  1. Install Ruby using RVM
  2. Install RubyGems
  3. Install Rails gem
  4. Install Passenger (gem install passenger)
  5. Install configured nginx using the passenger gem
  6. Install MySQL and create a user which my app will be able to access database from
  7. Clone the git repository and point the root of nginx to the public folder of the app
  8. Create the database, load schema and it’s done!
Normally, this procedure was enough to get an app flying in the sky. But when I opened the root page, I couldn’t find any styling, or images or javascript working. Basically, I had no assets being loaded. After looking at the source, I found that stylesheet and javascript was being linked to wrong paths. They linked to
stylesheets/application.css
and
javascripts/application.js
If I remembered correctly, they should have weird long name suffixes for caching purposes. And they should be served from assets directory and not stylesheets or javascripts. With this information, I went to google and searched a bit to find many people were having this problem. One solution was to precompile assets before serving them. So that is what I did by running the command
rake assets:precompile
Finally, I was able to get my styling done. I was able to see how beautiful bootstrap made the HTML look. I thought, finally, deployed it! Yayy. Back to creating a feature! Sadly, I had one more problem. Bootstrap comes with a set of icons and references it by simply putting the string of where is it located. Unfortunately, precompiling the assets meant that the string will be wrong because the file name will be different (Remember, weird long suffixes?). This was pretty easy to solve. I had two solutions. One was to override the Bootstrap variable and set it equal to image tag. I tried doing it, but then I figured, I will have to append .erb to the current file so as to be able to use
<%= image_tag "glyphicons" %>
I have no explanation to this, but I decided not use this method. Rather, I’ll do it the “unintelligent” way, and kept the images in public/img folder, the default location where Bootstrap expects it to be. This seemed to have done away all the problems I faced with a basic deploy of Rails app. Nothing big here, no caching and all, just plain small deploy. I know, many new people will be facing these problems, especially if they use this wonderful Bootstrap SASS gem. P.S. I am trying to organize the tutorials and guides and eBooks and stuff like that for new learners here. Currently, I am just allowing Rails and Django submissions. But, I myself won’t be able to do everything here, hope I am able to create a community of enthusiastic people who’d post stuff up there. Plus, higher amount of people would mean we’d be able to put in many new technologies there. New features coming up, I promise. Hope it helps the new learners! :)

Surprise Surprise!

| Comments

Remember I made a game 2 years ago just to get the feel of what Android platform was? Well, the game didn’t really take off back then but it seems to be creating (a very little) buzz right now. And why not, after all it did get featured at YourStory. :D I have no image to show so here is the video on how to play the game! So, after celebrating for days and days, me and Raghav decided to reboot the game and make it a little better so it does not hurt the eyes while playing and/or bore the player to death. With me recovering from the Jaundice I had just gotten and the exam season finally getting over, there seems to be plenty of time to do something of this sorts and use the time wisely. Hope to have little success this time.

Why Google+ Sign Up Is a Good Thing

| Comments

Google recently announced the Google+ sign in button which is very similar to the FB Connect button. So, why will the Google+ sign in be a better option than FB Connect? I read an article sometime ago which claimed that Social Login buttons aren’t effective. I couldn’t agree more. I even tested and verified the hypothesis. If you visit PollDaal’s homepage, you’ll find nothing (if you are logged out) except a link to sign in using facebook. But, in the navigation bar above, there is a separate sign in link too which allows people to sign up using only their email. Given that I have not mentioned anything about normal sign up process, I should not get, optimistically, more than 10% of my sign ups from email. Right? Wrong! Out of 90[1] registered people, a staggering 66 people have signed up using the sign up form. Sign up form was harder to find, more work to fill in details and yet around 75% of people chose to do that instead of one click Facebook connect. The only reason I feel people will do this is because they fear that their activity will be visible on facebook. Clearly, this is something people care about. Thus, they chose to go the hard way. Now, how is all this relevant with the Google+ sign up/sign in? There are many reasons why Google+ sign in will be a good thing to have. The biggest reason I’d love to use Google+ sign in will be the low amount of fear that what you share will be seen by others. Unlike facebook, Google+ account is owned by all but used by none. Thus, even if an application shared that I was listening to Justin Bieber, there will be relatively very very less amount of people who will get to know as compared to facebook. So even if an app finds a hack and keeps sharing posts, nothing will be seen by my friends thus reducing the damage to a great extent. Another reason I see why Google+ sign in should be a success is because whenever I was given a choice to login using Facebook, Twitter or Google (by HackerRank, for example), I found it more convenient to use Google as I knew in the back of my mind that nothing malicious could ever happen here. These kind of issues will obviously hamper the virality, but then again, the sort of virality gained by Facebook spamming dies in some time. Thus, developers will have to make the app so awesome that people deliberately share it on twitter instead of the app doing it for them, just like the God had intended it. Let me know what you think, G+ sign up, boon or bane? P.S. If you have an android device and you’ve updated an app within past two days, look for an automatically installed app, Google Settings. If you find it, let me know too. It feels like I am the only one who got it. [1] 90 registered people excluding the people I knew before, like my friends and mom (thanks ma!).

Easy Way to Organize Ruby Gems Using RVM Gemsets

| Comments

Finally, I have completely ported my workspace for PollDaal from Windows to Ubuntu. Windows is great, I have nothing against it, it just does not adjust well with Rails and the community is mostly on Unix based Operating System, thus making me search for any sort of errors for hours and hours because the first solution (and the continuing copy cat articles) assume you to be on Linux or Mac. So, after my 6th wubi installation, here I am, taming the might lion in the form of Ubuntu (12.04, Precise Pangolin). Now, there are many ways to install Ruby on Ubuntu but the easiest and most efficient one which I found was to use RVM. Trust me, you’ll love it! (Otherwise, trust me, I am an engineer, I know my shit, well, sorta..)

I trust you man, show me what you’ve got! Okay, first things first, what are gemsets? Well, if you have ever used someone else’s app on your machine, you might have noticed you need to use bundle command for their stuff, and many times, that breaks your app (Although, generally, running bundle install will make it work). This happens mostly because of other person using a different rails version and you trying to load that version and it’s dependencies which may or may not be already present in your machine. Isn’t there a way to manage gems differently for each project? What if a gem would work only for one project in which it is needed? Well, that is exactly what Gemsets are good at doing. Sounds interesting, how do I use them? Okay, for sake of not writing x.x.x for versions, let me assume you are going to use ruby-1.9.3-p125 version for your project. After installing rvm, in you console window write
rvm list
and press enter. If you see your version of ruby in the list (in our case, 1.9.3-p125) then move forward, otherwise write
rvm install 1.9.3-p125
and wait for it (Barney Stinson’s reference :P) to install. After you’re done with installation, write
rvm use 1.9.3-p125
to use (check this if it says rvm is not a function) and additionally you can write
rvm use 1.9.3-p125 --default
to make it a default choice for all the future generations using this machine. Great, now we have installed Ruby using RVM and are using our choice of version! Now do all the tricks you do to get started with rails. Some steps will be gem install rails, rails new billiondollarapp, cd billiondollarapp. After you’re done with looking at folders to your heart’s content, you have two options to organize your app using gemsets. Either do them manually or let RVM do it for you. If you want RVM to do it for you, all you have to do is
rvm --rvmrc --create 1.9.3-p125@billiondollarapp
This will create a heavily commented ‘.rvmrc’ file in your project folder. Try to read it. It shows you how you should do it, the correct way! This makes sure that all gems are loaded in a different directory for each ‘billiondollarapp’ you have. The down side being you have to download the same gems again and again for different projects. But you can download the common gems from outside the ‘billiondollarapp’ folder where there is no .rvmrc file. This makes them available as default for each environment. It will download the same gem again for your ‘billiondollarapp’ only if the version of gem required and default gem do not match. Do the bundle install for the app. And it’s done! The other way to do it is by writing
rvm gemset create billiondollarapp
in the terminal and then saving this line
rvm use 1.9.3-p125@billiondollarapp
by manually creating a .rvmrc file in the root directory of project. You can also just type this line in console to use it for the current session. There won’t be any problem in using either of the above way, I have been myself switching between the two methods, in my production machine, because I am that much of a badass! :D Now, whenever you try to run two different rails app one after the other, they won’t crash your apps.

Rails 3 Polymorphic Associations Explained (Somewhat)

| Comments

So, in past few days, I got requests from people to offer a Quiz type question at PollDaal. Being a nice fellow as I am (Modesty at its best!), I listened to them and started looking for ways to do it elegantly in Rails 3. After searching for a bit here and there, I got to know about polymorphic associations could be my saviour. I had learned earlier what they were but that was that. I quickly forgot them and thus they never came in my mind. So, someone said, teaching stuff makes you remember it. Thus, here I present, Polymorphic Associations 101 (kinda).

First things first, what are polymorphic associations?

Well,¬†With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model (visualized in the pic above). Don’t worry if you don’t understand the code written there. You will after reading this article (probably).

The most weird part of the above code seems to be the part which says

belongs_to :imageable, :polymorphic => true

This just means that the model Picture does not belong to any of the Employee or Product model but to something called Imageable.

Uh, oh. I was taught that models belong to models and nothing else. You can check any code which has belongs_to clause.

Well, that is kinda true, but we form a little twist while using polymorphic associations (if you forgot, they mean that it could be associated with many models). So, imageable here acts as an interface to link to for other models which link the same way they did except now they add a clause of as: :imageable. For example, the Person model now looks like:

class Person < ActiveRecord::Base
  has_many :pictures, :as => :imageable
end

You could have used any word in place of imageable, like picturable, photogenic, photograph, baklind, dhoni anything! They just have to match your column name.

Wait, what? Which column? What column? Which table?

Good question. You have to setup a reference in your Picture model to store the foreign key of the row it ‘belongs_to’. Now how do we do that? First, let us look at how we did for non-polymorphic associations. If, for example we have a Question model and Choice model, we say choice belongs to question and question has many choices. So, to make that thing work properly, we generally include a column ‘question_id’ in the ‘choices’ table. That thing generally works out without any problem and we live a happy satisfied life. But, there is no specific model assigned here in the polymorphic associations. What field do we use then? A wise man said, double the amount if you are not sure. Lets follow that wise man. We use two foreign keys! For the Picture case, they foreign keys are ‘imageable_id’ and ‘imageable_type’. The migration looks something like this,

add_column :pictures, :imageable_id, :integer
add_column :pictures, :imageable_type, :string

or you can use a handy trick provided by rails,

t.references :imageable, :polymorphic => true

Just run the migration now, add the snippets to your model, and congratulations. You successfully have configured a polymorphic association!

Yayy!! Well that was simple. Thanks man. Now, how do I actually reference it?

Ahh, the easy part. Let me assume that you know how to get data from model ( person = Person.find(23) ). There are two ways to create a reference, from the parent side or from child side.

person.picture = picture

or

picture.imageable = person

That is all really is there to assigning. Don’t forget to call save method on picture though, otherwise its gone as soon as the object stops persisting.

Seems simple enough, but I have a question. How do you use it to accept data from forms?

This is tricky and so I think I should leave it to experts. Check out this Railscasts. It shows how to do all this for comments. Ideal if you wish to create facebook and would need comments for all your Photo, Status, Video models.

You can either use the method shown by Ryan Bates in Railscasts or do manual assigning the way I showed. I prefer doing the manual assigning though. Easier to setup and less confusing. Plus, you have full control as you know where the code is and what it does.

I have one little trick which I’d like to share. As many people know, adding index to column in tables makes it for faster searching for data through that column, you all will be tempted to add index to both imageable_type and imageable_id columns by typing two migrations like this

add_index :pictures, :imageable_id
add_index :pictures, :imageable_type

And now, you should have faster finds, shouldn’t you? Well no! What we did was create two different indexes in the pictures table but we are always going to search for them together, instead we should do

add_index :comments, [:commentable_type, :commentable_id]

While we are at it, we can also limit the size of commentable_type column. We are storing it as a string but do you think we would really have a model name of 255 characters? Decreasing the size will also allow for smaller indexing and faster searching. We can limit the size by passing an option

:limit => 15

while migrating the database to get truly fast searching.

Have some of your little tricks or you think I did a mistake and a proved to be a bad teacher? Write it in the comments.

Announcing, PollDaal

| Comments

As many people know, I have been working on a project by the name of PollDaal. I’d like to announce, today, I’ve made enough to give a demo of this project.  

First “Startup Jaipur” Meetup

| Comments

If you’re based in Jaipur, you’d know how difficult it is to find people in the Web industry. I personally know at most 10 people who could make a website or design a website or have even a little knowledge about the internet industry. For most of the people, internet is pretty much restricted to Facebook. Thus, in a city dominated by¬†jewelers, how do you wish to network and connect with people of the - buzzword alert - startup ecosystem? Thus, to sustain and improve whatever ecosystem we have, I am trying to make a group of people who are trying or wish to create successful online products. So, since I am sooo creative, I have named it (for now) “Startup Jaipur”. Anyone can join it. There are no conditions to it. Open for all. But beware, most of the people will be from or around Jaipur. As of now, there is no official website but join the facebook group here to stay in touch. To get people to know each other, we’ll have meetups (You don’t say!) starting 16th of this month. Here is the link to the event. Do accept invitation if you are coming so I can plan ahead for the number of people attending. The venue is yet to be decided, so if you know about any place, feel free to mention them. The agenda of the meet won’t be much. Just getting to know each other. Believe me, I am making it sound boring, but it is very very exciting! Hope to see you soon! Ciao..