Skip to content

CODETUNES

This is Codetunes, a blog by Monterail, an offshore Ruby on Rails development agency.

Posts tagged “rails”

From Monterail with Love #1

A couple of months ago Bartosz described how we use Facebook to improve communication in our team. Actually most of the content on our wall are more or less interesting links from the internet. We quickly noticed a troubling pattern though—they are easy to forget. And if you forget them, you can’t use them.

So we decided that we’ll be regularly preparing a brief summary of the best content so it’s easy to find and convenient to browse. Our goal is not to provide The Hot News™—you can find them anywhere—but the top of the top stuff which we believe will remain valuable for a long time. So… let’s start!

JavaScript rules

Roy Tomeij, one of the speakers on the last wroc_love.rb conference, suggested that classes should be replaced with data-* attributes for JavaScript selectors. Recently he followed it up with some benchmarks and shared the numbers. If that doesn’t convince you, read why classes are for designers and data-behavior is for JavaScript developers.

If you have problems organizing your JavaScript assets when using Sprockets, you should read an awesome article from Unholy Rails: adding JavaScript to Rails.

Improve your tests

How to (and why) test factories—short and easy, but very useful protip from Thoughtbot.

If yours tests take too long, check if you can replace doubles with OpenStruct. Xavier Shay did some benchmarks on the subject.

There is new shiny tool on the horizon, Testacular, and I think it can soon replace Selenium. It allows to run tests in multiple browsers with your favorite testing engine under the hood. Read more in DailyJS article.

If you don’t feel comfortable writing tests, there is a new site for you: betterspecs.org, the collection of bad examples turned to good. It’s open-sourced so you can always add a new example or fix another if you disagree with proposed solution.

Coding patterns

DCI is a hot topic these days, but there is still lack of good examples, especially in Rails context. Victor Savkin fills this gap with an article Data Context Interaction: The Evolution of the Object Oriented Paradigm. If you like the solution proposed by Victor also check his gist collection and DCI-Sample repo.

Another interesting approach to DCI in Rails is shown on already mentioned Xavier Shay’s blog in article titled Dependecy Injection for Rails Controllers.

At last, an article about patterns themselves: The First Step to Applying Design Patterns: Don’t. Very good explanation why design patterns are awesome, when you should use them and when not.

See you next time!

Nginx+Unicorn configuration for multi-app servers

Platform as a service is getting more and more traction recently. However it doesn’t mean that one should start developing his applications with Heroku or Engine Yard in mind from now on. Self-managed solutions, be it own dedicated servers or using cloud infrastructure (like Rackspace Cloud), are still valid choices in most situations.

At Monterail we’re maintaining tens of web applications that are hosted in all of above-mentioned environments. We developed most of them, but there are also some legacy ones (even Rails 1.2 or PHP). So there is plenty of factors that affect hosting infrastructure, and basically each app need to be evaluated individually.

Outbound API rate limits: the nginx way

Implementing external API rate limits can be painful. There are some solutions that aim at this problem – let’s take Slow Web for example – but things tend to complicate when we start using background jobs, or even oldschool cron-rake setup. Slow web takes care of one environment at a time, not to mention that it relies on Net::HTTP so you can forget using more powerful stuff like Typhoeus.

Recently we started working on a project that uses heavily an API that limits our development calls to one per 500ms and production calls to one per 200ms (our first thought and initial information was that we can do five requests per second, but those are not the same). Inspired by a great post, „nginx JSON hacks”, an idea came to our minds. What if we could use nginx to implement limiting the API? Here comes the built-in nginx module, the HttpLimitReqModule. Let’s take a quick look.

http {
  limit_req_zone  $binary_remote_addr  zone=one:10m   rate=110r/m;

  server {
    listen       8080;
    server_name  localhost;

    location / {
      limit_req   zone=one  burst=100;

      proxy_pass        http://api.example.com/;
    }
  }
}

(Please bear in mind that this configuration is merely an example and you probably want a more comprehensive setup. You can hire us to do the job for you).

We set a simple proxy on localhost:8080, configure the limit_req_zone option, apply the zone, set the burst rate to 100 (depending on how you want to handle huge load, this could be smaller or bigger). We set the rate to 110 requests per minute for a little margin. Our benchmarks went fine, as we expected – no API calls were dropped. Setting it to exact 120r/m (or 2r/s) gave us some 403s, though.

Okay, so what about those cool examples in the post mentioned above? Let’s apply some caching!

http {
    limit_req_zone  $binary_remote_addr  zone=one:10m   rate=110r/m;
    proxy_cache_path  /tmp/nginx_cache levels=1:2 keys_zone=STATIC:64m inactive=60m max_size=128m;

    server {
        listen       8080;
        server_name  localhost;

        location /without_cache {
          limit_req   zone=one  burst=100;

          proxy_pass        http://api.example.com/;
        }

        location / {
            proxy_pass        http://localhost:8080/without_cache;

            proxy_cache STATIC;
            proxy_cache_methods POST GET PUT; # allow POST caching which is not allowed by default
            proxy_cache_valid 10s; # cache every API request for 10 seconds
            proxy_cache_key "$host$request_uri$request_body";
        }
    }
}

Why two locations, you may ask? It’s because we don’t want to have a rate limit for our cached version. In this case, when the first request finishes, every other gets an ultra-speed boost from being stored in a local cache.

We don’t have to worry about implementing API rate limits in every place in the app. We don’t have to worry about sharing those limits between different environments. All we need to do is to change the API host and enjoy pure coding goodness.

Turning off auto timestamping for testing in Rails

Suppose that you implemented a functionality that depends on values of created_at or updated_at fields of your models. How do you test it?

If you use fixtures that reside in test/fixture/*.yml files then there is no problem, because the values you set there for created_at and updated_at fields are saved to the database ‘as is’. So you can easily have an article created one week ago:

article:
  title: What a great day
  created_at:
  updated_at:

However, I don’t use fixtures files myself. I feel a bit dirty using them ;) I find fixture replacement tools far more maintainable. Namely, I love thoughtbot’s Factory Girl. But here comes the problem. This won’t work as expected with Factory Girl:

Factory(:article, :created_at => 1.week.ago, :updated_at => 1.week.ago)

That’s because ActiveRecord’s automatic timestamping feature sets Time.now for created_at and updated_at fields overriding our values. At least that’s ActiveRecord’s default behavior. Fortunately it can be disabled with:

Article.record_timestamps = false

Chances are that after creating a model with a custom timestamp we’ll want to turn automatic timestamping back on. But turning it off and on in many places in your unit tests would be pretty cumbersome. Wouldn’t it be cool if you could achieve all of this with a snippet below?

without_timestamping_of Article do
  Factory(:article, :created_at => 1.week.ago, :updated_at => 1.week.ago)
end

It turns timestamping off, executes the block and turns timestamping back on. I find it clean and dry. Here’s the code to place in your test_helper.rb:

# test_helper.rb
class Test::Unit::TestCase # or class ActiveSupport::TestCase in Rails 2.3.x
  def without_timestamping_of(*klasses)
    if block_given?
      klasses.delete_if { |klass| !klass.record_timestamps }
      klasses.each { |klass| klass.record_timestamps = false }
      begin
        yield
      ensure
        klasses.each { |klass| klass.record_timestamps = true }
      end
    end
  end
end

Of course you can turn off timestamping for many models at once:

without_timestamping_of Article, Comment, User do
  Factory(:article, :created_at => 1.week.ago, :updated_at => 1.week.ago)
  Factory(:comment, :created_at => 1.day.ago)
  Factory(:user, :updated_at => 5.hours.ago)
end

Hope you like it. If so, share :)

Speaking at IT Underground Security Conference and Workshop in Prague

it_underground_prague_125x125_enTomorrow I will be speaking at IT Underground Security Conference and Workshop in Prague, Czech Republic. That is three day long event that starts today.

I will give a talk on “Websecurity through conventions and best practices” which will be focused on securing web applications from the most common attacks with examples from Ruby on Rails web development framework.

Expect to see materials from the conf here in few days.

Rails 2.2.2, Ajax and respond_to

As I wrote some time ago in the article about Rails, Ajax and jQuery, sometimes there are problems with Rails not interpreting correctly content type headers of ajax requests. It’s because not all web browsers send that header in the same way. 

What I proposed was to sort the request.accepts array (array containing content type headers sent by browser) so that xml content type would be the first element. That would then trigger format.xml in our respond_to block.

However that approach does not work in Rails 2.2.2, because now the request.accepts array is frozen and it cannot be modified. I spent some time googling for the solution, but with no effect. So I dived into the API and Rails’ source code and came up with pretty nice and simple solution to the problem.

class ApplicationController < ActionController::Base
  before_filter :xhr_to_xml

  def xhr_to_xml
    request.format = :xml if request.xhr?
  end
end

This piece of code is an equivalent of the snippet I proposed in the article I referred to at the beginning. Now all ajax request will trigger format.xml in respond_to blocks.

Materials from AIESEC Conference in Częstochowa, Poland

Last month the netguru team has been invited to Corporate Responsibility and Information Technology Conference organized by AIESEC (international student organization) which took place in Częstochowa, Poland. We went there and gave some talks on various topics and I think some of you may find materials from this conference quite interesting.

First, we led an unofficial discussion on “The (fading) differences between desktop and web applications”. We introduced the topic to our hearers and then let them express themselves, it was quite successful.

On Day 2, we organized Ruby on Rails workshops which consisted of “Introduction to RoR” talk and one-hour live-coding session during which a simple twitter like application has been developed. You can find the results on our Github account.

We finished Day 2 with a talk on Enterprise 2.0 and on Day 3 we talked about “Developing a web-development company (startup)”, which was quite different from what people heard on earlier talks gave by the representatives of big corporations. I have no materials to share on this, though. Sorry.

Rails, Ajax and jQuery

The more ajaxified application, the more fun it is to use. But it is also more painful do develop. What is written below is my approach to pairing Rails and Ajax. It’s a mix of tips I found over the net on blogs and forums. I use jQuery for JavaScript, but I don’t use jRails or any JS/Ajax helper methods provided by Rails. Note that all Javascript/HTML code presented here can be used even if you dont use Rails or Ruby as your web development platform. Let’s begin.

Rails is RESTful

Thanks to Rails’ RESTfulness the only thing to take care of server side is setting proper response in controllers’ actons.

class PostsController < ActionController::Base
  def index
    @posts = Post.find :all
    respond_to do |format|
      format.html
      format.xml { render :xml => @posts.to_xml }
    end
  end
end

Rails decides which format block to call basing on routes defined in routes.rb file (map.connect ‘:controller/:action/:id.:format’) and accept headers sent with request by the client.

In most cases we want Ajax requests to trigger format.xml blocks in our controllers’ actions, so we need to set proper accept headers. Let’s do it just once with application-wide setting.

// All ajax requests will trigger the format.xml block
// of +respond_to do |format|+ declarations
$.ajaxSetup({
  'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/xml")}
});

Browsers’ quirks

There is something worth noting here, a problem I had once with IE and Safari. The code above may work differently in various browsers. Browser set text/html accept header by default. Here IE and Safari will append text/xml to it so you’ll get something like ‘text/html; text/xml’, while Firefox will replace text/html with text/xml and you’ll get ‘text/xml’ only. This is very important because Rails will take the first format it detects in accept header and trigger respective block in controller’s action, which will be html for IE and Safari. Here’s a fix for this that shifts application/xml (if it is present) to the beggining of accept headers array.

class ApplicationController < ActionController::Base
  before_filter :correct_safari_and_ie_accept_headers

  def correct_safari_and_ie_accept_headers
    request.accepts.sort!{ |x, y| y.to_s == 'application/xml' ? 1 : -1 } if request.xhr?
  end
end

Ajaxify your links

Here’s a quick way to ajaxify your existing links. Add this JavaScript to your application.js file.

jQuery(document).ready(function() {
  // All A tags with class 'get', 'post', 'put' or 'delete' will perform an ajax call
  jQuery('a.get').livequery('click', function() {
    var link = jQuery(this);
    $.get(link.attr('href'), function(data) {
      if (link.attr('ajaxtarget'))
        jQuery(link.attr('ajaxtarget')).html(data);
    });
    return false;
  }).attr("rel", "nofollow");

  jQuery('a.post').livequery('click', function() {
    var link = jQuery(this);
    $.post(jQuery(this).attr('href'), "_method=post", function(data) {
      if (link.attr('ajaxtarget'))
        jQuery(link.attr('ajaxtarget')).html(data);
    });
    return false;
  }).attr("rel", "nofollow");

  jQuery('a.put').livequery('click', function() {
    var link = jQuery(this);
    $.post(jQuery(this).attr('href'), "_method=put", function(data) {
      if (link.attr('ajaxtarget'))
        jQuery(link.attr('ajaxtarget')).html(data);
    });
    return false;
  }).attr("rel", "nofollow");

  jQuery('a.delete').livequery('click', function() {
    var link = jQuery(this);
    $.post(jQuery(this).attr('href'), "_method=delete", function(data) {
      if (link.attr('ajaxtarget'))
        jQuery(link.attr('ajaxtarget')).html(data);
    });
    return false;
  }).attr("rel", "nofollow");

  jQuery('a.get, a.post, a.put, a.delete').removeAttr('onclick');
});

Just add a CSS class .get, .post, .delete, or .put to a link to make turn it into an ajax-link. I recommend you use LiveQuery plugin which will automatically bind click events to new links that appear on the page (loaded with Ajax call for-example). You can optionally set ajaxtarget attibute of the link. It expects a selector of a container in which you want to place the response.

link_to 'my cool article', article_path(@article), :class => 'get', :ajaxtarget => '#article_container'

Ajaxify your forms

For this you’d need jQuery Form Plugin.

  jQuery('form.ajax').livequery('submit', function() {
    jQuery(this).ajaxSubmit();
    return false;
  });

Now all your forms that have “ajax” class will be submitted via Ajax.

...

CSRF and authenticity token

Rails has built-in protection from cross-site request forgery attacks. It relies on an authenticity token which Rails look for when dealing with POST, PUT or DELETE requests, so this token needs to be sent by the browser together with the request. The token is automatically added as a hidden field to any form you create with form_for method, it is also attached to links that have :method param set to :post, :put or :delete. In fact the token is added dynamically by Javascript code placed in link’s onclick attribute. However in one of code snippets above we stripped that onclick attribute from links to prevent the page reload after we click the link. Now we need to attack that token ourselves. First we will alter our application layout:


  <% if protect_against_forgery? %>
    
  <% end %>

Now we need to ensure that the token is sent together with ajax requests.

jQuery(document).ready(function() {
  // All non-GET requests will add the authenticity token
  // if not already present in the data packet
  jQuery("body").bind("ajaxSend", function(elm, xhr, s) {
    if (s.type == "GET") return;
    if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return;
    if (s.data) {
      s.data = s.data + "&";
    } else {
      s.data = "";
      // if there was no data, $ didn't set the content-type
      xhr.setRequestHeader("Content-Type", s.contentType);
    }
    s.data = s.data + encodeURIComponent(window._auth_token_name)
                    + "=" + encodeURIComponent(window._auth_token);
  });
});

We’re done, we have our ajax requests protected from CSRF attacks.

Modifing page after Ajax calls

Standard way to do page modification after Ajax call is to use Javascript code that inserts content returned by the call somewhere on the page. The other method is to put the modifying code in views that are returned by the server and just execute it in the browser. For this I’d recommend another jQuery plugin – Taconite. As the author says: “The jQuery Taconite Plugin allows you to easily make multiple DOM updates using the results of a single AJAX call. It processes an XML command document that contain instructions for updating the DOM”. Thanks to this you can for example easily use flash messages in your Ajax views.

Let this be a part of your usual layout:

><%= flash[:notice] %>

Now let this be your taconite layout you’d use when returning views for Ajax requests:


  
  <% if flash[:notice] %>
    
      <%= flash[:notice] %>
    
    
  <% end %>
  <%= yield %>

This will display flash notice messages with fade-in effect after Ajax requests. Similarly you can update other elements of the page.

What’s in your toolbox?

I would love to hear from you on how you deal with Ajax in your web applications. What libraries/plugins do you use?

Custom thumbnail generation with Paperclip

Paperclip is a great plugin for Ruby on Rails which eases the pain of image upload and resize process. The usage is very simple, results are what you want in most cases. Not in all cases though.

Your role is only to define the sizes of thumbnails that will be generated from original image. Thumnailing in is fact done by calling ImageMagick’s convert command with -scale argument, for example convert -scale ’640×480>’.

You can alter how exactly the image is scaled by appending modifiers to desired thumbnail size, like ‘>’ in ’640×480>, however it won’t give you unlimited power over thumbnailing process.

Consider following example. I have a small image (120×120).

Scaling it to smaller size gives me the result I want. But when the result image needs to be bigger than original, the original image is enlarged in a way that you’ll see single pixels.

What I want to achieve is the enlargment done not by scaling the original image, but by adding a border around it.

This cannot be achieved by adding any of modifiers to desired thumbnail size, so why not to pass additional arguments to convert command? Yes, that would be a solution.

And here’s my solution – PaperclipExtended. It’s a plugin that modifies original Paperclip, so that now it accepts additional (optional) parameter :commands when defining the thumbnails sizes.

class User < ActiveRecord::Base
  has_attached_file :avatar, :styles => { :medium => "300x300>", :small => "100x100>" },
    :commands => { :medium => "-background white -gravity center -extent 300x300 +repage" }
end

During thumbnail generation Paperclip will now append given commands to convert command. Convert command for medium style will be now:
convert -scale ’300×300>’ -background white -gravity center -extent 300×300 +repage
Convert command for small style will remain unchanged.

Passing such commands will help me with the enlargment I mentioned above. For what else could be done check the documentation of ImageMagick’s command line options.

PaperclipExtended is not a replacement for Paperclip, just an extension. It works with version 2.1.2 of Paperclip plugin (the current one and the only one I tested). Compatibility with future version is not guaranteed.

I put a plugin on GitHub.
http://github.com/netguru/paperclip-extended

How to install:

script/plugin install git://github.com/netguru/paperclip-extended.git

Configuration is the same as of original Paperclip plugin, but you can now add an optional :commands parameter.

Hope it’ll be helpful!

If you have any questions, post them in comments to this post.