Rack Metrics is dead, long live Rack Metrics!

28 Aug 2014 By: Greg Molnar

About 6 months ago, I built a performance monitoring tool for rack based applications. I released the tool at a pretty early state, showed it a few people, even got a few paying customers, but it didn't take off they way I wanted. So I took my next contract job and haven't had the time to carry on the work on the app.

I enjoyed that contract so much, I decided to stay as a permanent employee with the company and I realised the best thing to do with rack metrics, is to make it open-source. There is work needs to get done on it and I don't have the resources to get it done, but the community will hopefully move it forward. So as of today I made the code public. The code could be nicer, better at a few places so PRs are welcomed!

The 2 gems are under their own organization: https://github.com/rack-metrics

Read more

Rails Fixtures

12 Jun 2014 By: Greg Molnar

Fixtures are the officially supported way to handle test data and lately they are getting some attention finally. I guess I am not the only developer who started with FactoryGirl because there was more tutorials about it that time, and it seemed a really great way to handle test data as a junior ruby developer. As time went by, the projects I was working on grew and I realized that my test suite's speed issues are mostly related to my factories. So I decided to give a shot to Fixtures. It was a quite positive experience and fixtures made a huge impact on the speed of test runs. But enough of the story about me let's see how can you use fixtures with Rails.

Fixtures are stored in a yaml file but they are also processed with ERB before sent to the yaml parser, so we can use Ruby to make them dinamic. Let's use the good old blog example:

# posts.yml
post_one:
  id: 1
  title: First Post
  published_at: <%= 1.day.ago %>

post_two:
  id: 1
  title: Second Post
  published_at: <%= Time.now %>

You would also want to handle relations too with your test data and fortunately that's not an issue with fixtures. You can simply use the "label" to reference another fixture:

# users.yml
greg:
  name: Greg
  email: ...

# posts.yml
post_one:
  title: First Post
  author: greg
  published_at: <%= 1.day.ago %>

As you see, there is a simple reference to the user model in the posts.yml which will setup the relation. You can also implement somewhat of an inheritence in your fixtures by using the DEFAULTS label:

# posts.yml

DEFAULTS: &DEFAULTS
  active: true
  tags: "foo, bar"

post_one:
  title: First Post
  author: greg
  <<: *DEFAULTS

post_two:
  title: Second Post
  author: greg
  <<: *DEFAULTS

This can be handy if your fixtures shares multiple attributes with the same values.

Brandon Hilkert also shared his 7 reason of switching to fixtures and Minitest, which is a great reading: 7 REASONS WHY I'M STICKING WITH MINITEST AND FIXTURES IN RAILS

I hope this little write up will make you to give a try to fixtures if you are not using them now.

Read more

Rails Caching Again

04 May 2014 By: Greg Molnar

In the previous post I covered how can you use Rails' Russian Doll caching to make you app super fast. I didn't cover though how to cache search result pages and paginated results, so here comes the second part of that article.

I made a sample application where I have a product listing page with pagination and a search form: https://github.com/gregmolnar/rails-caching

Read more

Rails Caching

18 Apr 2014 By: Greg Molnar

I've built a Kanban board as a side project and I want to share how much performance boost I was able to give it by implementing a Russian Doll Caching.
The app itself is a typical kanban board where you can setup different stages for the tasks and they are in the column of the appropriate stage. I have a project where I have 4 stages: To-do, In progress, Waiting for review, Done. On this board I have 138 tasks in the moment. According to Rack Metrics this page takes between 1485 and 1678 ms to get ready on the server side. This is way too slow in my opinion so I will dig in a bit more. I randomly picked one of the request to this route and I saw there the following:

Duration:  1598.14ms
View runtime:   1485.152174ms
DB runtime:   78.776503ms
Render calls:   140

There are 140 render calls because I use partials and every task on the board triggers a render call. This is a great place to utilise some caching.

Read more

Rails 4.1 - My favourite changes

07 Mar 2014 By: Greg Molnar

Rails 4.1 is coming out soon and I'd like to summarize which new features I like the most.

Spring Application Preloader

Spring preloads your application which makes your test runs a lot faster. Rails 4.1 generates the binstubs with spring so when you call rails or rake spring will handle the call. If you want to run a command without spring you can do so by using bundle rails or bundle rake. Another change I'd like to mention here is two new rake task to run the tests:

rake test:all
rake test:all:db

The first command merges your different types of test(model, controller, integration, mailer) and runs them. It also does not reset your db so your tests should run faster. The second one does the same except it resets the db between the test.

config/secrets.yml

You may have used figaro before to keep the sensitive data out of your repo but from now on Rails provides a built-in solution to this problem. Rails 4.1 generates a secret.yml in the config folder and you can store api keys, etc in it. The syntax as follows:

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
  some_api_key: SOMEKEY

If you want to access these in your application you can do so by calling Rails.application.secrets.some_api_key.

Action Pack Variants

Mobiles and Tablets are widely used these days and from Rails 4.1 we can easily separate the templates for the different clients. You need to set the variant in your controller:

case request.user_agent
when /iPad/
  request.variant = :tablet
when /iPhone|Android/ # far from complete. just for the sake of example
  request.variant = :phone
end

And in your respond_to block you can render a separate view:

respond_to do |format|
  format.html do |html|
    html.tablet # renders app/views/projects/show.html+tablet.erb
    html.phone { extra_setup_if_needs; render ... }
  end
end

Active Record enums

With this extension to ActiceRecord you can declare an enum field in your model and Rails will handle the mapping of integer values in the database column to human friendly values in your code.

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

It also defines handy utility methods:

conversation.active?  # to see if the record is active
conversation.active!  # to set the record active

It also makes easy to implement a simple state machine. I am already using this feature in production and it works like a charm.

CSRF protection from remote script tags

I use RJS to update parts of the applications via ajax and as homakov pointed out in the past this was vulnerable to XSS. To fix the security issue Rails will use CSRF protection if the request is not xhr.

Added Numeric#in_milliseconds

In the past I always wrote x * 1000 to convert timestamps I used on the client-side but now this is handled by this syntax sugar.

These are the changes I like the most but you can find an exhaustive list of changes in the changelog, thanks to Yves and Godfrey.

Read more

How I test Rails validations?

25 Feb 2014 By: Greg Molnar

I often get the question from new rubyist "How should I test my model validations in Rails?". A simple example is when we have a Post model with two required fields:

# app/models/post.rb
class Post < ActiveRecord::Base
  validates_presence_of :title, :body
end

You could write a test like this:

# test/models/post_test.rb
require 'test_helper'

class PostTest < ActiveSupport::TestCase
  test "should not save post without title or body" do
    post = Post.new
    assert_not post.save
    post.title = 'Test'
    assert_not post.save
    post.body = 'Test body'
    assert post.save
  end
end

But this test is already too long and what if you have a lot more required fields? To get around this it is better to test if the validation errors are correct:

# test/models/post_test.rb
test "should have the necessary required validators" do
  post = Post.new
  assert_not post.valid?
  assert_equal [:title, :body], post.errors.keys
end

Now we cover the existence of the validators with a lot shorter and simpler test. We can use the same approach to test ther validation rules like numericality:

# app/models/post.rb
class Post < ActiveRecord::Base
  validates_presence_of :title, :body
  validates :score, numericality: true, allow_blank: true
end
# test/models/post_test.rb
test "should have numeric score" do
  post = Post.new(title: 'test', body: 'test body', score: 'test')
  assert_not post.valid?
  assert_equal ["is not a number"], post.errors.messages[:score]
end

And so on. As some of the readers pointed out if you need a full blown solution with support of on and etcetera thoughbot's shoulda-matchers is has all that.

Read more

How to test your gem against multiple version of Rails?

19 Feb 2014 By: Greg Molnar

If you develop a gem which integrates with Rails you may want to test against multiple versions of it. My solution to this to use one page Rails applications with the appraisals gem and load the applications based on the actual gem version. Let me show you an example:

bundle gem example
      create  example/Gemfile
      create  example/Rakefile
      create  example/LICENSE.txt
      create  example/README.md
      create  example/.gitignore
      create  example/example.gemspec
      create  example/lib/example.rb
      create  example/lib/example/version.rb
Initializing git repo in ~/Github/example

We generated a gem skeleton. Let's prepare the gem for testing. We need to add some dependencies to the gemspec:

# example.gemspec
...
spec.add_development_dependency 'minitest', '>= 3'
spec.add_development_dependency 'appraisal'
...

Read more

How to test an autocomplete with Rails and Minitest?

29 Oct 2013 By: Greg Molnar

An autocomplete is a nice example for an ajax driven feature and I will demonstrate how to test such a features with Rails 4 and Minitest. First we will create a sample app and setup Minitest and Capybara for integration testing.

rails new rails-autocomplete-test

We need to add capybara and the poltergeist driver to our Gemfile:

group :development, :test do
  gem "capybara"
  gem 'poltergeist'
end

After we ran bundle we need make some changes to the test_helper.rb:

require "capybara/rails"

class ActionDispatch::IntegrationTest
  include Capybara::DSL
  require 'capybara/poltergeist'
  Capybara.javascript_driver = :poltergeist

  def teardown
    Capybara.current_driver = nil
  end
end
class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil
  def self.connection
    @@shared_connection || retrieve_connection
  end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection

First we require the capybara/rails module than set the javascript driver to poltergeist. I am also setting the current_driver of capybara to nil after each test because I want to use poltergeist only when we are testing javascript features so the rest of the test suite can run faster. Than we make ActiveRecord to share the same connection between threads because capybara starts the browser in a different thread from the one our application uses and it wouldn't access to the same data in these threads. If you want to know more why we need do do this you can read Jose Valim's explanation on this link. Now we have a setup to test our javascript features so let's write a test for an autocomplete form field.

Read more

Page caching with Rails 4

20 Oct 2013 By: Greg Molnar

The built-in page caching has been extracted to a separate gem in Rails 4 and here is a guide how to use it. First we need to add the gem to our Gemfile:

gem 'actionpack-page_caching'

Than in the application controller we need to specify the folder to store our cache files:

class ApplicationController < ActionController::Base
  include ActionController::Caching::Pages
  self.page_cache_directory = "#{Rails.root.to_s}/public/page_cache"
end

Let's say we have an article controller and we want to cache the index and the show action:

class ArticleController < ApplicationController
  caches_page :index, :show
  # Rest of the file omitted.
end

Read more

Rails' rescue_from

02 Oct 2013 By: Greg Molnar

rescue_from is a very useful method in Rails. It lets us to catch exceptions and pass them to a callback or a block. A typical usecase is to handle ActiveRecord::RecordNotFound errors like in this example:

FooController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: not_found

  private
  def notfound
    message = "Foo with ID #{params[:id]} not found."
    logger.error message
    redirect_to not_found_url, info: message
  end
end

In the example above whenever an ActiveRecord::RecordNotFound raised in the scope of the FooController it will be caught and the notfound method will log the event than redirect to the notfound page with a message to display in the browser. Since rescue_from works with a block too we can refactor the above as follows:

FooController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound do |exception|
    message = "Foo with ID #{params[:id]} not found."
    logger.error message
    redirect_to not_found_url, info: message
  end
end

Another case when rescue_from comes handy is when we use cancan for authorization and we want to handle the authorization errors. We can do so by add the following to the application controller:

rescue_from CanCan::AccessDenied do |exception|
  redirect_to root_url, :alert => exception.message
end

As you see in this case we display the exception message set by cancan. If you want to use rescue_from from in a class which does not inherit from ActionController::Base you just need to mixin the ActiveSupport::Rescuable:

class Foo
  include ActiveSupport::Rescuable
end

Read more

Travis CI Multi Database Rails

27 Sep 2013 By: Greg Molnar

I started to use Travis CI for continous integration. They have a free plan for open source which makes a good opportunity to try out the service. Travis supports various runtimes and databases and I was going to test my app against ruby 1.9 and ruby 2 and 3 different databases: sqlite, mysql, postgres. To setup these runtimes I created a travis.yml config file like this:

language: ruby
rvm:
  - 2.0.0
  - 1.9.3
env:
  - DB=sqlite
  - DB=mysql
  - DB=postgresql

We need a bit more work to make this work though as we need to specify the database config for each runtime. In my Gemfile I decide which database gem to bundle from the database config but on travis that won't exists so the bundle command will fail.

Read more