Saturday, November 15, 2014

Use FactoryGirl And Faker for easy data generation in unit testing (Part1)

The  most irritating thing in writing tests is the data generation preparation process, sometimes you want to create an object with 20 fields that 10 of them are mandatory but you only care about the value of 1, and you don't want to mock, cause you interact with other methods and object that fetch this model from db.

To me it happens a lot so I found the FactoryGirl + Faker combination that made my life much more easy and now I can write tests in peace.

To add them just put in Gemfile:

 gem "factory_girl_rails", "~> 4.0"
  gem "faker"

So lets take a complex sample to explain all there is to know.

We have a User, the User belongs to a Company, User has many tasks.

Company has many irritating mandatory fields

Lets define the Company Factory:

FactoryGirl.define do
    factory :company do
      name {Faker::Name.name}
      trp {Faker::Number.between(0,10)}
      grp {Faker::Number.between(0,5)}
      budget {Faker::Number.number(4)}
      cpm {Faker::Number.between(1,70)}
      trp_price {Faker::Number.between(100,700)}
      viewer {Faker::Number.between(0,100000)}
      total_viewer {Faker::Number.between(0,200000)}
      unique_viewer {Faker::Number.between(0,50000)}
      spots {Faker::Number.between(0,1000)}
    end
  end

As you can see I define lots of fields with random values.

Now we can create a company by writing
create(:company)
Or just build one (without save to db) by calling

build(:company) 

That's all for now, I'll continue in part2.
 
 

Get the user locale from http headers

If you want to provide default localization support for guest user in your website yo can locate their browser locale by the following code:


def extract_locale_from_header
    unless request.env['HTTP_ACCEPT_LANGUAGE'].nil?
      return request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
    end
    'en'
  end

This way you can determine on server side the locale of the user currently entered your site.

Dedicating a DJ(Delayed job) worker to a specific queue in heroku.

Let's say you have a vey important procedure that takes a while, and you need to process it in background, but you still want to execute ASAP.

I'm using Delayed Job on Heroku, and could not find a lot of tutorials to do this simple task.

So here is the simplest way to achieve this ability, you can raise a process/deamon  that will have only one queue to work on. (Dealyed job worker by default is queue agnostic, just process all jobs)

In procfile:

urgentworker:  QUEUE=urgent bundle exec rake jobs:work

You can call the worker in any name you want and even define multiple workers for multiple queues.
And in the "urgent" job just define the queue name to be "urgent" the worker will process only jobs in this queue.

example:

handle_asynchronously :some_job, :queue => "urgent'

This will also work for Resque.

Notice that for rescue you can write QUEUE=* but for delayed job you can't.

Overriding default id in mongoid

This is an easy one, just want to make sure it's clear.

Add the following field to your model:


field :_id, type: Moped::BSON::ObjectId



And to allow setting it:

1 def id=(id)
2   self[:_id] = id
3 end


Now you can just do obj.id=[Some ObjectId] and save the object.