Posts tagged "rails"

I’ve been playing a lot with Rails 3 lately, it’s completely awesome! However, we don’t have any Rails 3 app in production at the moment, all projects that Plataforma has been doing for its clients so far are using Rails 2.3.5. Since I was already having fun with Rails 3, I thought I should also give ruby 1.9 a try. Ok, so how could I have Rails 2.3.5, Rails 3, ruby 1.8.7 and ruby 1.9 in my machine without going crazy? The answer is RVM (Ruby Version Manager)!

RVM is an awesome tool that gives you the power to have as many rubies in your machine as you want, and the best of all, all versions are isolated, no conflicts at all. In order to install it, follow the instructions inside RVM’s site. After that, I installed ruby 1.9.1 through RVM with rvm install 1.9, installed all the gems necesssary to play with Rails 3 (gem install rails --pre) and then, I could start to play.

I was playing with that configuration successfully until the moment I got a segmentation fault error. Other people got the same error too. Thankfully the problem didn’t last too long, this was one of these moments which I was very happy for having a Rails Core member in my team (@josevalim). He told me that Rails 3 doesn’t support ruby 1.9.1, actually, it’s supporting ruby 1.9.2! So, I needed to install a new ruby version, and install all Rails 3 gems again, damn it! But, I was fortunate enough for being using RVM.

In order to install Ruby 1.9.2-head and Rails 3 gems, all I needed to do was:

  1. Update my RVM: rvm update --head
  2. Install ruby 1.9.2 head: rvm install 1.9.2-head
  3. Create a Rails 3 RVM gemset: rvm --create use 1.9.2-head@rails3
  4. Copy my already installed Rails 3 gems to my new RVM gemset within my ruby 1.9.2: rvm gemset copy 1.9.1 1.9.2-head@rails3

That’s all! After that, I was back to the game! Man, RVM is awesome!!!

Be sure to have a look at a Wayne’s gist about how to install Rails 3 with RVM, and, check out RVM’s Gemsets feature, it’s very useful.

And you, do you have any tips about dealing with many versions of ruby and/or Rails, or about RVM?

We have been working in a project which deals with date events and we needed a recurrence feature in the application. An initial implementation could simply work with Rails ActiveSupport and use its Date helper methods, in order to shift by day, week, month and others.

>> Date.today
=> Thu, 15 Apr 2010
>> Date.today.next_month
=> Sat, 15 May 2010
>> Date.today.next_week
=> Mon, 19 Apr 2010
>> Date.today.next_week(:thursday)
=> Thu, 22 Apr 2010
>> Date.today.advance(:days => 4)
=> Mon, 19 Apr 2010

Very easy, right? But what if we now want events that occur every monday or sunday? Or events that happen at each two weeks? For each new case, we will need to add and deal with more and more logic.

Instead we have been using the Recurrence gem, created by Nando Vieira with some contributions by José Valim (yeah, our good fellow ;)). Recurrence works with ActiveSupport as its base for date calculation and provides a simple DSL to work with recurring events. Let me show a simple example:

# events every day, considering today as Apr 15th.
>> r = Recurrence.new(:starts => 2.days.ago, :every => :day, :until => Date.tomorrow)
>> r.events
=> [Tue, 13 Apr 2010, Wed, 14 Apr 2010, Thu, 15 Apr 2010, Fri, 16 Apr 2010]

If no :until is determined, it runs until year 2037 (maybe the end of world? No, it’s when the unix time 32-bit overflow…). You can check the Github repository and this blog post (in brazilian portuguese) to learn different use cases and examples for Recurrence.

Now I want to show you how we integrated it with our application. We have built an EventRecurrence class which deals internally with the recurrence logic.

# app/models/event_recurrence.rb
# It has :start_date, :every and :end_date as database columns
class EventRecurrence < ActiveRecord::Base
  def dates(options={})
    options = {:every => every, :starts => start_date, :until => end_date}.merge(options)
    options[:on] = case options[:every]
    when 'year'
      [options[:starts].month, options[:starts].day]
    when 'week'
      options[:starts].strftime('%A').downcase.to_sym
    when 'day', 'month'
      options[:starts].day
    end
    Recurrence.new(options).events
  end
end

Notice we need to setup the options hash for different cases (day, week, month and year) because the configuration options changes for each. Now, accessing all the recurring dates for one model is quite easy:

>> er = EventRecurrence.new(:start_date => Date.today, :every => :month, :end_date => 6.months.from_now)
>> er.dates
=> [Thu, 15 Apr 2010, Sat, 15 May 2010, Tue, 15 Jun 2010,
Thu, 15 Jul 2010, Sun, 15 Aug 2010, Wed, 15 Sep 2010, Fri, 15 Oct 2010]

Since EventRecurrence is a model, these options are saved in database and we can update or use them for querying freely. For instance, if we want to look for all dates in a given period, we just search for all EventRecurrences that are in the range and collect the dates returned by recurrence. Here you can see a raw implementation of this idea:

class EventRecurrence < ActiveRecord::Base
  # Retrieves a list of all dates for a period
  def self.dates_between(start_date, end_date)
    # Filtering EventRecurrence on the period using a between named scope
    recurrences = EventRecurrence.between(start_date, end_date)
 
    recurrences.inject([]) do |dates, recurrence|
      # Use the given dates instead of the ones in the DB
      dates.concat(recurrence.dates(:starts => start_date, :until => end_date))
    end
  end
end

This is just an initial post showing some ideas to get you going with recurring events. If you are interested, there is a lot of information related to this topic, like Recurring Event in Calendars, an article by Martin Fowler, and the iCal RFC2445 which includes calendar specifications.

And you, have some different solutions about recurring events to share with us?

Two months ago we were celebrating Devise’s birthday. We were not talking about its age, Devise had just 4 months of life, but we were happy to reach the 1.0 release.

Today we are celebrating again! We are very proud and glad to have Devise in its first Railscast! Ryan Bates has done a great job explaining how to get Devise up and running in a Rails 3 application, showing how to install Devise and choose the basic modules you want to use in your application.

We also made a promise to you: get Devise up and running for Rails 3. We keep walking this road, each Rails beta version released we are releasing a new compatible Devise version. For the time being, we have Devise 1.1.rc0, a release candidate version, compatible with Rails 3 beta 2.

We are looking forward to see the second part of Devise’s Railscast, about how to configure Devise to fit the needs of your application.

Give Devise a try. You can post your questions to the mailing list and, if you find any issue, please use the Github Issue Tracker. Don’t forget to post information about your environment (like Devise, Warden and Rails versions) including the stack trace if you are facing an error, to help us help you =). Enjoy!

Update: Railscasts just released the second part of Devise screencast, Customizing Devise, going through Devise configuration options. Check it out!

Rails is very friendly whenever you need to create forms to input data to your web app’s database. Things get a little different when you must have forms and you don’t want to save anything in the database. For that, you have to resort to other ways, maybe creating tableless models.

However, there are some simple cases that even creating a new class seems an overkill, such as forms for searching or filtering data in your app. In these cases, you just want a form that user can pick options and hit a button to see the results. When returning to the user, it is expected to have that form filled with the options the user had chosen before, but there is no simple, clean way to do that with plain old “form_tag”. Here is where our little tip comes in.

OpenStruct is a cool lib that comes with the Ruby Standard Library. “It is like a hash with a different way to access the data” says the documentation:

>> user = OpenStruct.new({:name => 'John', :last_name => 'Doe'})
=> #<OpenStruct name="John", last_name="Doe">
>> user.name
=> "John"
>> user.last_name
=> "Doe"
>> user.bla
=> nil

We can use it to fool our old friend “form_for” helper to think we’re dealing with normal AR objects, so we can create a method that wraps “form_for”, simple as this:

require 'ostruct'
module SearchFormHelper
  def search_form_for(object_name, options={}, &block)
    options[:html] = {:method => :get}.update(options[:html] || {})
    object = OpenStruct.new(params[object_name])
    form_for(object_name, object, options, &block)
  end
end

Inside the view, you will do the same way you do with AR models:

<% search_form_for :search do |f| %>
  <p>
    <%= f.label :start_at %>
    <%= f.date_select :start_at %>
  </p>
  <p>
    <%= f.label :end_at %>
    <%= f.date_select :end_at %>
  </p>
  <p>
    <%= f.submit 'Search' %>
  </p>
<% end %>

That’s pretty much it! If you’re filtering data, by a category for example, try checking the has_scope plugin, works like a charm in combination with this tip, but it is a matter for other post.

And you, reader, do you have any little tricks like this? If you don’t mind, share with us!

We have been having some projects lately that needed a lot of admin CRUDs and pages showing a list of attributes, and we were getting bored of copy and paste code like this in our show pages, for every single attribute:

<p>
  <strong class="label">Name</strong><br />
  <%= @person.name %>
</p>

We had already created some helper to do the work for us, but having this helper being copied from one project to another wasn’t that DRY. That’s when we decided to create ShowFor.

ShowFor is a DSL to help you showing a list of attributes, with I18n, perfect for show pages in CRUD interfaces. It allows you to replace code/html duplication in your views using a nice syntax. Let’s see what we can do.

Attributes

Let’s imagine we have a Person model, which has first_name, last_name, age, photo, and confirmed attributes. The following lines show a list of values for a specific person:

<% show_for @person do |p| %>
  <%= p.attribute :first_name %>
  <%= p.attribute :last_name %>
  <%= p.attribute :confirmed? %>
  <%= p.attribute :created_at, :format => :short %>
  <%= p.attribute :age, :if_blank => "No age" %>
 
  <% p.attribute :photo do %>
    <%= image_tag(@person.photo_url) %>
  <% end %>
<% end %>

Here is an example output you will get:

<div class="show_for person" id="person_1">
  <p class="wrapper person_first_name"><strong class="label">First name</strong><br />Carlos</p>
  <p class="wrapper person_last_name"><strong class="label">Last name</strong><br />Antonio</p>
  <p class="wrapper person_confirmed"><strong class="label">Confirmed?</strong><br />Yes</p>
  <p class="wrapper person_created_at"><strong class="label">Created at</strong><br />08 Mar 11:30</p>
  <p class="wrapper person_age"><strong class="label">Age</strong><br />24</p>
  <p class="wrapper person_photo"><strong class="label">Photo</strong><br />
    <img alt="Rails" src="/images/rails.png?1268047643" />
  </p>
</div>

As you can see, you are going to get a default html markup, with classes and ids to help you design with CSS. And if you noticed, we are using extra options in some attributes, lets take a look at some of them:

  • :format lets you pass any format that will be used together with i18n, for date/time attributes only, as you would use with the l helper.
  • :if_blank specifies what to show if the attribute is blank. It may have a default value from i18n.
  • do...end: using blocks you can handle the content for that specific attribute by yourself, as we have done in this example for the photo attribute.

Boolean attributes, as our :confirmed, also have a default for true and false values, and can be configured through i18n. If you want to say “Yup” and “Nope” instead of “Yes” and “No” respectively, just change your i18n file. You can also pass a :escape option to not escape the value (true by default).

Associations

ShowFor also works with associations. For instance, we can easily add that a Person belongs to a City with a name attribute and that it has and belongs to many Tags. To handle the former, we can do:

<%= p.association :city %>

ShowFor will guess the right attribute to show by looking into all possibilities configured in ShowFor.association_methods and in this case choosing :name. But of course, you can change it as you need, on-the-fly:

<%= p.association :city, :using => :full_name %>
<%= p.attribute :full_name, :in => :city %>

Both calls above will have the same output, just choose the one which suits you better.

Handling collections is easy as belongs_to associations. You can just pass the association to ShowFor and it will know whether it’s a collection or not, generating a list of elements using ul and li tags.

<%= p.association :tags %>

However, if you want to render the collection inline, you can use :to_sentence or :join as options:

<%= p.association :tags, :to_sentence => true %>
<%= p.association :tags, :join => ',' %>

It’s also possible to pass a block to the collection. ShowFor will create the wrapper tag (ul by default in this case) and will yield each element in the collection for you to handle it:

<% a.association :tags do |tag| %>
  <li><%= link_to tag.name, tag %></li>
<% end %>

Labels

You may have noticed ShowFor has a default label using the strong html tag. It also exposes you this as a helper, so you can use it whenever you wish:

  <%= p.label :first_name %>
  <%= p.label :age, :id => 'person_age' %>
 
  <strong class="label">First name</strong>
  <strong class="label" id="person_age">Age</strong>

Installation

ShowFor is already compatible with Rails 3, at the time of this writing in version 0.2.0. You can just follow the instructions in the README to get it installed.

If you are using Rails 2.3.x, take a look at the 0.1 branch, and follow the installations in the README for this branch to get it up and running.

Please don’t forget to run the generator and take a look at the initializer, it will allows you configure several parts of ShowFor.

script/generate show_for_install

Closing

ShowFor helps you to show your objects easily with a default html markup, and can be totally configured to suit your needs. It has been helping us in every project, and we hope it may help you too. If you have any doubt, please take a look at the README, there are a lot of examples and documentation there.

And what about you? Do you have any helper you use every single day that might be transformed in a plugin/gem? Do not hesitate on doing this, we would be glad to see your work.

Enjoy!

RailsMetrics is a new Rails engine which stores everything that is happening inside your application in the database, so you can profile each request, besides creating charts, statistics and extract useful information.

I’ve been working on it for the last couple months in parallel with ActiveSupport::Notifications, which is the foundation for RailsMetrics, and it was open sourced today by Engine Yard!

It was a challenging project due to its threaded nature and I will share a couple things I learned during the process in this blog later. For now, you can watch the screencast below to see what it does and how to install it:

Rails Metrics Screencast – Feb/2010 from PlataformaTec on Vimeo.

As said in the video, getting it released is just the first step and now it’s your turn to fork and improve it by providing a better layout, creating new reports, charts, etc!

In case you are interested here are some screenshots that I tweeted earlier: http://twitpic.com/13e7fn/full and http://twitpic.com/13e7h2/full.

The javascript novell

A week ago I asked what people uses to create charts in Rails so I could evaluate what would be the best library to use in RailsMetrics. There were three types of libraries: server side ones, flash and javascript. Since I don’t want to depend on having neither RMagick nor Flash installed on the developer machine, I chose the javascript kind.

After some research I ended up with three libraries: g.raphael, flot and jqplot.

For RailsMetrics, I chose to use g.raphael since I can easily manipulate the objects it creates and it is the one which looks better (at least imho ;)). However it has poor documentation and the default charts have poor customization options compared to the other two libraries, so you end up tweaking the chart by hand (which was fine in my experience).

I’m waiting for your pull requests, enjoy!