//DEVGURU

Paweł Smoczyk @ 2010-01-22

Rails class diagrams

Sometimes it’s hard to remember model attributes and relationships between them. Especially when you are new to the project, diagrams can be very helpful. I came across Railroad gem when I was searching for the right tool. It can generate controller diagrams with inheritance hierarchy and model diagrams with attributes and associations. Output is in the DOT language. Generated .dot files can by processed by Graphviz into .svg or .png format. If you have Omnigraffle you can import .dot files and edit them.

Michał Bielawski @ 2009-12-15

Truncate string preserving only full words (Ruby, RoR)

Easy method to cut string to a defined length without leaving words cut in half.

class String
  def truncate_full_words limit = 64, completion = "..."
    self.length > limit ? "#{self[0..(self.rindex(' ', limit) || limit)-1]}#{competion}" : self
  end
  def truncate_full_words! limit = 64, completion = "..."
    self.replace(self.truncate_full_words limit, completion)
  end
end

Usage:

>> some_string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec enim nibh."
=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nec enim nibh."
>> some_string.truncate_full_words
=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ..."

Have fun using it :)

Marcin Stecki @ 2009-12-10

Proudly presenting has_uniq_token.

In one of our rails projects, we found that a lot of models needed some sort of unique token or guid generated before saving. Most of them were then used in routes or something similiar, but all of them were generated by callbacks in each model. Since that methods were mostly effect of copypasta, i decided to abstract the code, and make a plugin of it.

A bit of meta programming later, i’m proud to present the results: http://github.com/netguru/has_uniq_token/

Hope you find it useful.

Michał Bielawski @ 2009-11-18

How to convert doc/xls/ppt/… to pdf in Unix console

Today we needed to make a tool to convert Microsoft Office (and preferably other formats) documents to PDF from a Rails application. We have come up with such solution – install OpenOffice.org, CUPS and CUPS-PDF (virtual PDF printer for CUPS) and run it like this:

soffice -headless -pt Cups-PDF file.doc

This command executes OpenOffice.org in so-called ‘headless’ mode – meaning that it will not run anything graphical. It reads the file.doc, and prints it using CUPS-PDF virtual printer. The resulting PDF can be found (by default) in ~/PDF directory.

Marcin Stecki @ 2009-11-17

Validating email in rails

That’s pretty basic stuff but if you wonder how to validate email in rails check out this plugin:

http://github.com/dancroak/validates_email_format_of/

Good luck.

Marcin Stecki @ 2009-10-30

Simple trick to use sql dump in rails

Fastest way to use sql dump when riding Ruby On Rails.

script/dbconsole < dumpname.sql
Marcin Stecki @ 2009-10-26

Ruby and RoR – picking every n-th element of an array

def every_nth(nr)
self.in_groups_of(nr).map(&:first)
end
def every_nth!(nr)
self.replace(self.every_nth(nr))
end
Picking every n-th element of an array might look like this: (via @d3x)

Define:


class Array
  def every_nth(nr)
    self.in_groups_of(nr).map(&:first)
  end
  def every_nth!(nr
    self.replace(self.every_nth(nr))
  end
end

and use:


>> (1..9).to_a.every_nth(3)
=> [1, 4, 7]
Michał Szajbe @ 2009-05-09

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:
[sourcecode lang="yml"]article:
title: What a great day
created_at: < %= 1.week.ago.to_s(:db) %>
updated_at: < %= 1.week.ago.to_s(:db) %>
[/sourcecode]

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

Hope you like it. If so, share :)

Michał Szajbe @ 2009-04-17

Dynamic cookie domains with Rack’s middleware

Handling sessions in multi-domain environment is not the simplest things to do, because of the fact that cookies are scoped to a domain they were set by.

Recently we were developing an application with such an idea in mind:

  • Application will work as a base for other mini-applications (which we call sites)
  • Each site can be accessed via different url types: site.example.org and example.org/site
  • We want the users to remain logged in when switching from one url type to another

I won’t be covering application structure, routing, etc. here, I will only write about maintaing the sessions is such an environment.

So this is pretty simple here – all that we needed to do was to set cookie domain to .example.org (note the “dot” at the beginning). This could be done via:

ActionController::Base.session = {
  :domain => ".example.org"
}

However there was an additional requirement that we need to deal with:

  • Each site can be accessed via custom domain – site.com
  • Of course there’s no way here to keep the user logged in when he’s switching from site.com to example.org/site or site.example.org, at least it cannot be done with setting cookie domain to whatever value

Technically, to access the site via site.com, that domain must point to our IP address. Then we need to detect that the site is being accessed via custom domain and set cookie domain respectively.

This could be done via some funky before_filters in an Application Controller, however we found much better and cleaner way.

Rack’s middleware to the rescue

Rack itself is a minimal interface between web server and your ruby framework. It’s used by Ruby on Rails (since 2.3) and Merb. The request comes from web server, goes through middleware layers and enters the application.

So we wrote a middleware layer that detects the host with which our application is accessed and sets cookie domain for the request. Here it is:

app/middlewares/set_cookie_domain.rb

class SetCookieDomain
  def initialize(app, default_domain)
    @app = app
    @default_domain = default_domain
  end

  def call(env)
    host = env["HTTP_HOST"].split(':').first
    env["rack.session.options"][:domain] = custom_domain?(host) ? ".#{host}" : "#{@default_domain}"
    @app.call(env)
  end

  def custom_domain?(host)
    domain = @default_domain.sub(/^\./, '')
    host !~ Regexp.new("#{domain}$", Regexp::IGNORECASE)
  end
end

Now we need to turn it on:

environment.rb

config.load_paths += %W( #{RAILS_ROOT}/app/middlewares )

production.rb

config.middleware.use "SetCookieDomain", ".example.org"

.example.org is the default domain that will be used unless the application is accessed via custom domain (like site.com), we give it different values depending on environment (production/staging/development etc).

And since we’re fans of test driven development, here’s the test that ensures us that everything works as expected:

tests/integration/set_cookie_domain_test.rb

require 'test_helper'

class SetCookieDomainTest < ActionController::IntegrationTest

  context "when accessing site at example.org" do
    setup do
      host! 'example.org'
      visit '/'
    end

    should "set cookie_domain to .example.org" do
      assert_equal '.example.org', @integration_session.controller.request.session_options[:domain]
    end
  end

  context "when accessing site at site.com" do
    setup do
      host! 'site.com'
      visit '/'
    end

    should "set cookie_domain to .site.com" do
      assert_equal '.site.com', @integration_session.controller.request.session_options[:domain]
    end
  end

  context "when accessing site at site.example.org" do
    setup do
      host! 'site.example.org'
      visit '/'
    end

    should "set cookie_domain to .example.org" do
      assert_equal '.example.org', @integration_session.controller.request.session_options[:domain]
    end
  end

end

Test is sponsored by great Shoulda and Webrat gems.

Feel free to comment and share.

Bartosz Pietrzak @ 2009-04-08

Work environments of Rails developers #1: Ryan Daigle

Taken from Ryan’s blog:

Ryan Daigle is an independant developer working as Y|Factorial, LLC, a ruby and iPhone software consultancy.

He also writes Ryan’s Scraps, the “What’s new in edge rails” blog.

Bartosz Pietrzak: Which OS and which editor are you using?
Ryan Daigle: I’m on Mac OS X which means that I use Textmate  for most of my work.

Do you prefer GIT or SVN?
I prefer GIT, although I’m not a GIT master, but I do prefer it.

Do you see any upsides or downsides of using GIT, comparing it to SVN?
Well, certainly there are a lot of benefits, like easy branching, low cost branching and things of that nature. As far as downsides, I think it’s more complex tool, so it takes a little more effort to become very efficient at it, but that’s hardly a downside. It just means that it might require a little more effort to become good at using that tool.

What plugins or gems do you usually generate your new apps with?
Let’s see… I use HAML, make resourceful, rspec, cucumber, all those gems. Let me open up one of my projects right now. Will_paginate, HAML and  make resourceful – these are the core ones that I tend to at least start with.

What’s your strategy for populating your database with some predefined data? Do you use migrations, fixtures, rake tasks with gems like populator?
For staging data, for data that I just want to populate the database to play with the app I usually have a rake task that use something like factory girl or, there’s a plugin I highly recommend, called dataset, which is a fixture replacement, but it lets you load predefined set of data with one rake task. So I use that for staging data and if it’s setup data, configuration data for the application that needs to be present in production and staging, then I usually write a custom rake task, but the point being I keep it out of my migrations, because I don’t think that migrations are the place to do data population. Migrations are place to alter the structure of your database and occasionally, in the course of altering the structure of the database you do need to tweak or change something, but as for data population I keep it out of my migrations.

What is your opinion on TDD?
My opinion is that it’s great and it’s certainly what I choose to use to start things off. There are many different tools that you can use in TDD but as far as general methodology is concerned I certainly am keen on it.

You’ve mentioned Rspec. What do you think about Shoulda?
I’ve obviously heard about Shoulda, Mocha and they seem to have good reputation, I’d just not had the least recognition needed to anything other than rspec, so I’m still using rspec and haven’t really looked into the others. Although recently I started doing Cucumber, Webrat and rSpec, it’s kinda my testing stack and I’ve enjoyed that process.

How do you think Rails development process will change after 3.0 release?
Oh, that’s a tough one! I mean, I’ve not seen much actual work come through on the Rails source on github so it’s hard to say if most of the changes will have limited  external effects and mostly just internal tweaks and refactorings, although I think one of the stated goals will be to make rails a little more componentized, a little more accessible without of monkey patching rails classes to overwrite functionality and add new functionality, I think they gonna try to give you more predefined points at which you can hook into their functionality, so I think for plugin writers and gem writes and engine writers I think the development process will be a lot cleaner and a lot more stable, as far as everyday developers I’m not quite sure yet how they’ll be impacted.

What usually do you do with your team first, design of the applications or the you know, code and the functionality of the applications?
When you say design, do you mean visual design?

Yes.
Ok, so usually when I start on a project I like to have at least wireframes in place so I like for my client to have at least thought about the functionality that their users will see, but I don’t necessarily want the visual design in place, I don’t need to see fonts, sizes and colors and pretty graphics, I just need to know how the client’s envisioning their functionality will be exposed to the user. And then when I start on, my preference is to have visual design kinda be done in parallel, or at least maybe week or two in front of development, I feel like if you treat visual design and development as two separate deliverables, then often in the end, when you try to bring those two sides together there’s a lot of work that goes into melding the two, so if you can treat it as one highly integrated process throughout your outcome will be much better. So, in the beginning I do like to see a visual representation of the functionality that needs to be developed, but I don’t need to see a visual design.

Do you prefer the getting real way of creating the applications or huge specifications?
Well, certainly I’m against huge specs of any kind, so I would have to come down on the side of getting real, I feel like not everybody has a luxury of such a freeform process as getting real, but certainly the main tense of that thought process I do support.

These will be private ones, do you prefer working from home or from office?
I think there are definitely benefits to an office, but I think if you are working with a group of people that you’re familiar with, and you know their work style, and you trust the work they do I think working from home can be more productive since you’re outside of the realm of those frequent interruptions that happen in office and really let you be quite productive, so I think for my productivity sake I enjoy working from home and occasionally it makes sense to get together to discuss something in person, but for the majority of the time I think working from home is beneficial.

Do you prefer night time or day time and what about separating work from private life?
I’m not a morning person but I start my day pretty early, because I like to have my work done somewhat early, so that I can have the late afternoon and evenings for myself, for personal time, so come 4:30 or 5 o’clock I usually, you know, I don’t turn off my computer but I put it away wherever I go, go running, go to the gym or do something like that and force myself to get out of the house and that’s serves as my formal break between work time and personal time. And then the weekend it’s the same thing, I don’t really feel compelled to go to my home office and start working on the weekends, it’s just structured that way, so I don’t really think about that. It doesn’t mean everything’s done during the week. Maybe I’ll just fire off some emails, but I don’t really get into core work mode during personal time.

Michał Szajbe @ 2009-03-27

Websecurity through conventions and best practices

Let me present you materials from a talk I gave at IT Underground Conference in Prague on 24.03.2009. The title of a presentation is “Websecurity through conventions and best practices” and it’s focused on securing web applications from the most common attacks with examples from Ruby on Rails web development framework.

The slides include all speaker’s notes.

Bartosz Pietrzak @ 2009-03-26

Useful gems: Quick Scopes

Some time ago I’ve found an useful gem – internuity’s quick scopes.

As readme for the plugin says,

A Rails plugin to automatically add some quick named_scopes to your models.

These are especially useful for quick modifications to a query on an association.

It creates default named_scopes for any of your models:

  • order
  • limit
  • offset
  • with – alias for :include
  • where – alias for :conditions

Personally I don’t like mixing named_scopes with :conditions and :order options – with this gem we can chain our scopes with limit, order etc:

  user.posts.order('created_at')

  user.posts.where(:published => true)

Another small thing that makes our code cleaner.

Bartosz Pietrzak @ 2009-02-21

Colors in GIT

This one will be short:

git config --global color.ui true

The command above will color your git output (branches, file status etc) green and red. Very, very handy.

Bartosz Pietrzak @ 2009-02-19

The Ultimate Website Launch Checklist

websitelaunchGuys form Box UK released “a checklist that all websites should be checked against before launch“. It’s full of “oh, I know that!”, but I can imagine finding it very helpful when estimating project due dates and, of course, when launching the website/app – because you probably won’t remember some of them. Pretty cool.

Michał Szajbe @ 2009-01-31

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.