Finalist

Finalist Developers Blog

Ruby on Rails 2.3

18 March 2009 11:34 · Iain Hecker · Ruby

Vanaf eergisteren is officieel de stabiele versie van Ruby on Rails 2.3 (versie 2.3.2 dus) de deur uitgegaan. Omdat er nogal wat wezenlijke toevoegingen en veranderingen aan het framework zijn gedaan, bespreekt Iain enkele highlights van deze release.

Eerste stap richting Rails 3

Afgelopen kerst kregen we een fraai cadeautje: Rails en Merb gaan samen verder door het leven. Dus versie 3 van Rails is gelijk aan versie 2 van Merb. In het kort betekent dit dat we Rails als full stack framework houden, maar met makkelijk wisselbare onderdelen, een stabiele API waar plugin developers tegenaan kunnen praten en een serie snelheidsupgrades. Rails 2.3 plukt de eerste vruchten van deze samenwerking. ActionPack heeft een overhaul gekregen. De broncode is nu een stuk duidelijker en makkelijker aan te passen. Yahuda Katz, de main developer van Merb houdt op zijn blog bij wat hij verandert, interessant leesvoer!

Het renderen

Het renderen van templates en partials met nog kortere syntax. Een voorbeeld:

# In Rails <= 2.0
render :partial => "post", :collection => @posts
 
# In Rails 2.1 en 2.2
render :partial => @posts
 
# In Rails 2.3
render @posts

Opstarten

Verder gebruikt Rails nu Lazy Loading, dus onderdelen van Rails worden pas geladen zodra ze gebruikt wordt. Dit brengt de opstarttijd van het framework terug van meer dan 10 seconden naar minder dan een seconde. Erg handig om snel wijzigingen te zien in de Rails configuratie. Ook worden onderdelen die je nooit gebruikt niet in het geheugen geladen.

Gem dependencies

Rails 2.3 kent nu het verschil tussen gems die nodig zijn voor development en gems die nodig zijn voor het draaien van je applicatie. Het commando rake gems:unpack zal nu alleen de gems bij je applicatie bundelen die nodig zijn voor deployment, maar andere gems, zoals test-frameworks en de (beruchte) gem builders (echoe, hoe, etc) niet.

Templates

De naam Templates is wat verwarrend. Het gaat hier dus om templates voor Rails zelf, niet voor views. Het is nu mogelijk om scripts te schrijven voor het instantieren van een Rails applicatie. Wil je bijvoorbeeld standaard RSpec gebruiken? Schrijf een script dat heel snel deze taak op zich kan nemen. De Rails Templates hebben een mooie syntax om dit te doen:

if yes?( "Wil je RSpec gebruiken?" )
  gem "rspec"
  gem "rspec-rails"
  generate :rspec
  run "rm -r test/"
end

Engines

Engines is een herleving van de oude components. Engines betekenen dat het nu weer mogelijk is om routes en views met de plugin mee te bundelen. Je kan in je plugin een app-directory zetten en daar de gebruikelijke Rails-onderdelen in zetten. Een view kun je aanpassen naar wens door hem opnieuw te maken in de applicatie zelf. Effectief betekent het dat je een onderdeel van je applicatie makkelijk in een plugin kan gieten. We komen weer een stap dichter bij de holy grail van software development: herbruikbare code.

Rack

Rails is over naar Rack. Rack is een web application interface die nu door alle frameworks in Ruby gebruikt wordt. Elke Rack applicatie kan nu op dezelfde manier requests ontvangen en stuurt ze op dezelfde manier terug, iets wat goed nieuws is voor applicatieservers zoals Mongrel en Passenger. Deze interface is ook uit te breiden met zogeheten middleware. En omdat alle frameworks tegenwoordig Rack gebruiken, werkt deze middleware dus voor meer dan alleen Rails.

Metal

De complete stack van Rails is niet bepaald snel. Met Metal biedt Rails een hulpmiddel om sommige acties wat te versnellen. Metal acties gaan buiten Rails om en je bent zelf in staat om je eigen response terug te geven aan Rack in de vorm van een statuscode, een headers-hash en een body. In lang niet alle gevallen is dit handig, maar het kan je helpen bij die acties die net wat meer snelheid nodig hebben en geen behoefte hebt aan de functionaliteit die ActionController je biedt.

Nested Forms

Een formulier maken waarin een object met zijn relaties bewerkt kunnen worden, is tamelijk vervelend. Rails 2.3 biedt hiervoor een hulpmiddel in de vorm van Nested Forms. Dit is het makkelijkst uit te leggen met een klein voorbeeld.

class Project < ActiveRecord::Base
  has_many :tasks
  accept_nested_attributes_for :tasks, :allow_destroy => true
end

En vervolgens in je view:

- form_for @project do |project_form|
  %p
    = project_form.label :name
    = project_form.text_field :name
 
  - project_form.fields_for :tasks do |task_form|
    %p.task
      = task_form.label :name
      = task_form.text_field :name
 
      = task_form.label :_delete
      = task_form.check_box :_delete

Er zijn nog veel meer mogelijkheden en opties. Het kunnen opgeven wanneer een taak als niet verzonden beschouwd mag worden, wat te doen met validatiemeldingen en het geheel in een enkele database commit zetten zijn een paar voorbeelden.

i18n updates

Natuurlijk moet ik het ook even over internationalisatie (i18n) hebben. In Rails 2.3 kunnen templates hun eigen locale hebben. Als de taal op “nl” is gezet zal Rails eerst “index.nl.html.haml” proberen te openen, daarna de ingestelde default locale en daarna de template zonder locale in de filename. Ook de errorpagina’s kunnen geïnternationaliseerd worden (404.nl.erb en 500.nl.erb)

Ook zijn er in views automatische scopes toegevoegd. Als je vanuit app/views/projects/show.html.haml de code t(".foo") aanroept (met een puntje ervoor dus), zal dat vertaald worden naar t("projects.show.foo").

Dynamische scopes

Een beroemd onderdeel van ActiveRecord zijn de dynamische finders die al in eerdere Rails-versies zaten. Hiermee kon je Cow.find_all_by_name("berta") doen, en wat Ruby-magie regelde de rest, zonder dat je de find_all_by_name methode hoefde te implementeren. Sinds Rails 2.1 zijn er named scopes, waarmee je een stukje SQL een naam kon geven en zo deze kon chainen. Nu zijn deze twee functionaliteiten gecombineerd tot dynamische scopes. De volgende code levert maar 1 SQL-query op:

Cow.scoped_by_name("berta").scoped_by_age(10).scoped_by_stable(8)
# SELECT * FROM cows WHERE name = 'berta' AND age = '10' AND stable = '8'

Ook kun je nu een default_scope opgeven, die standaard aan alle queries wordt meegeven, zoals het sorteren op naam etc.

Natuurlijk kan je alle verschillende soorten scopes door elkaar gebruiken.

Batch processing

Van tijd tot tijd moet je iets doen op een enorme hoeveelheid records in de database. En als je een paar duizend records hebt, dan kost dat nogal wat geheugen omdat voor elk record een object geïnstantieerd wordt. Met de methode find_each los je dat probleem op, door iedere keer maar 1000 records te pakken, deze te behandelen en dan de volgende 1000 regels. Dit kan aanzienlijk schelen in geheugengebruik.

Documentatie

De officiële guides zijn praktisch af. Kijk op http://guides.rubyonrails.org/ om deze nuttige guides te lezen!

Een complete lijst met veranderingen vind je hier.

Conclusie

Zoals altijd zitten er een hoop leuke features in de nieuwe release. Ik heb nog niet elke nieuwe feature evenveel aandacht gegeven, maar het ziet er allemaal veelbelovend uit. Genoeg om me het komende half jaar bezig te houden tot Rails 2.4 en 3.0 uitkomen!

Share and Enjoy:
  • email
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Blogosphere News
  • Fleck
  • NuJIJ
  • Slashdot
  • StumbleUpon
  • LinkedIn
  • Twitter

Reageer

RSS feed for comments on this post · TrackBack URI