Rails & Bash

Geplaatst door Michiel de Mare vr, 14 nov 2008 19:15:00 GMT

Ik breng een groot deel van mijn tijd in de OSX terminal door. (Hoeveel? Dit jaar 358 uur en 33 minuten. Thank you RescueTime )

En ik was van plan om een artikeltje te schrijven over de bash history, maar tijdens mijn research ontdekte ik dat dit artikel al bestond.

Dus lees het, en neem de adviezen over! (Of heb je al een HISTSIZE van één miljoen?)

In plaats van mijn artikel dus een aantal rails-relevante aliassen:

# de snelste manier naar een mysql prompt
alias dbd='./script/dbconsole development'
alias dbt='./script/dbconsole test'

# rake validate checkt de syntax van alle ruby-bestanden
# in mijn project.
alias gca='rake validate && git commit -a'

# diff en status commando's die weten of ze svn 
# of git moeten gebruiken
alias dif='if [ -d ".svn" ]; then svn diff; else git diff;fi'
alias st='if [ -d ".svn" ]; then svn st; else git status;fi'

# op mijn server is dit een alias naar production
alias sco='./script/console'

alias cdw+='cap deploy:web:enable'
alias cdw-='cap deploy:web:disable'

# commit naar testomgeving en run autotests
# als iets faalt krijg ik een mailtje
alias gpu='git push slice && cap autospec'

# een deploy kan even duren
# het 'say' commando vertelt me wanneer de deploy klaar is.
alias cdp='git push gitserver && cap deploy_all \
&& say "deployed on production"'

# shortcuts om in te loggen op al mijn servers
alias shmi='ssh michiel@mijnserver.com'

# snel een nieuwe alias aanmaken en laden
alias ebp='mvim ~/.bash_profile'
alias sbp='source ~/.bash_profile'

# nog een paar rails-afkortingen.
alias rmi='rake db:migrate'
alias rti='rake test:integration'
alias rtf='rake test:functionals'
alias rtu='rake test:units'

Wie heeft er nog meer handige deploy-tips?

Geplaatst in  | Tags ,  | geen reacties

Enumerable#otherwise

Geplaatst door Remco van 't Veer vr, 07 nov 2008 11:02:00 GMT

Hoe vaak heb je niet iets als het volgende geschreven?


if results.empty?
  puts "no results" 
else
  results.each do |result|
    puts "- #{result}" 
  end
end

In een poging om alle lijsten in een web applicatie te kunnen voorzien van een mededeling dat de lijst leeg is, zijn we tot de volgende constructie gekomen:


results.each do |result|
  puts "- #{result}" 
end.otherwise do
  puts "no results" 
end

Door simpelweg Enumerable uit te breiden met:


module Enumerable
  def otherwise
    empty? ? yield : self
  end
end

Hiermee kan je ook:


results = search_terms.otherwise{['kittens']}.map{|term| search(term)}

Als je de otherwise methode ook nog eens in de NilClass stopt maakt het zelfs niet meer uit of search_terms in het bovenstaande voorbeeld nil of een lege collectie is.

Geplaatst in ,  | 4 reacties

Rails I18n scopes

Geplaatst door Remco van 't Veer vr, 17 okt 2008 18:19:00 GMT

Op dit moment ben ik in een team druk aan het bouwen aan een site voor een startup. Een vereiste voor deze applicatie is dat deze meertalig uitgevoerd moet worden. Gelukkig wordt er hard gewerkt om Rails 2.2 uit te rusten met I18N en zijn we dus op edge gedoken om van deze goodies gebruik te kunnen maken.

Een aardige eigenschap van de i18n api is het gebruik van scopes. Hiermee kan je je vertalingen netjes georganiseerd houden. Waar ik echter al snel tegenaan liep is dat ik in m’n templates steeds weer dezelfde scope aan het doorgeven was;

<%= t.label :user_name %>
<%= t.text_field :user_name %>
<div class="help">
  <%= t(:user_name, :scope => [:user, :register, :help]) %>
</div>

<%= t.label :password %>
<%= t.text_field :password %>
<div class="help">
  <%= t(:password, :scope => [:user, :register, :help]) %>
</div>

Natuurlijk had ik ook het volgende kunnen schrijven:

  <%= t('user:register:help:user_name')

Maar eigenlijk wil ik:

  <%= t('user_name', :subscope => :help) %>

of:

  <%= t('help:user_name') %>

schrijven.

Gelukkig is dat helemaal niet moeilijk! We hebben nu het volgende in onze application helper staan:

# Override translate method to consider translate_scope.
def t(text, options = {})
  scope = (translate_scope.dup << options.delete(:subscope)).compact
  super(text, {:scope => scope}.merge(options))
end

# Append scopes to the current translation scope.
def with_translate_scope(*scopes)
  translate_scope.concat(scopes)
  yield
  scopes.size.times{translate_scope.pop}
end

# The current translation scope, default to current controller name.
def translate_scope
  @translate_scope ||= [controller.controller_name]
end

De translate_scope methode beheert de huidige scope. Als basis scope wordt de controller naam gebruikt. De with_translate_scope verwacht een scope en een blok waarin deze scope actief zal zijn. Ten slotte wordt de t methode overschreven om deze scopes te gebruiken en om een extra optie subscope te accepteren.

Hiermee kan het eerdere voorbeeld herschreven worden tot:

<% with_translate_scope [:user, :register] do %>
  <%= t.label :user_name %>
  <%= t.text_field :user_name %>
  <div class="help">
    <%= t(:user_name, :subscope => :help) %>
  </div>

  <%= t.label :password %>
  <%= t.text_field :password %>
  <div class="help">
    <%= t(:password, :subscope => :help) %>
  </div>
<% end %>

Beter? Toch?

Geplaatst in ,  | 2 reacties

Rails MVC aan je laars lappen met Mongrel handlers

Geplaatst door Remco van 't Veer ma, 24 dec 2007 11:18:00 GMT

Module View Controller is mooi maar soms moet je heel creatief zijn om een oplossing in die mal te proppen. In dergelijke gevallen is een meer lowlevel aanpak veel doeltreffender. In het geval waar ik tegenaan gelopen ben, wil ik audio streams serveren vanuit een Rails applicatie. Om precies te zijn: ik wil MP3 bestanden automatisch omzetten naar een lager bitrate en deze over het netwerk sturen zodat er aan de andere kant naar geluisterd kan worden. Daar is weinig MVC aan, al is het alleen maar dat er niets te view-en valt!

Nog even in het kort, was is Mongrel? Mongrel is een webserver (grotendeels) geschreven in Ruby. Ruby versie 1.8 is standaard uitgerust met een web server genaamd WEBrick maar deze is niet snel en efficient genoeg voor openbare productie web applicaties. Mongrel daarentegen is een kruising tussen een windhond en een poedel, snel en niet stuk te krijgen. Het beestje is multi-threaded en kan daarmee honderden aanvragen tegenlijk afhandelen.

Lees verder...

Geplaatst in , ,  | 5 reacties

Migraties, data en model classes

Geplaatst door Remco van 't Veer vr, 22 jun 2007 14:01:00 GMT

Migraties is m’n op een na favoriete Rails ingrediënt. Het is ook het onderdeel wat me al te veel lastige problemen heeft bezorgd. Natuurlijk kan je tests schrijven voor je migraties met behulp van MigrationTestHelper. Maar daar tackle je de hoofd brekers niet mee; data migraties en constant evoluerende model classes.

Een voorbeeld!

Lees verder...

Geplaatst in ,  | 1 reactie

Het testen van een testloze Rails applicatie

Geplaatst door Matthijs Langenberg do, 26 apr 2007 14:55:00 GMT

Veel applicaties zijn niet vanaf het begin geschreven met goede tests (of helemaal zonder tests). Hoe ga je te werk wanneer je je Rails omgeving gaat upgraden, of wanneer je grote aanpassingen gaat maken in je code?

In een ideale wereld zou je alleen je test suite alleen te hoeven uitvoeren: De reden dat ik altijd zo hamer op het schrijven van testen, het liefst door middel van een test-first aanpak als Test Driven Development of Behaviour Driven Development. Helaas is deze ideale wereld vaak een utopie.

Enkele weken geleden heb ik me bij Newminds bezig gehouden met het migreren van een applicatie (die niet met een test-first aanpak is geschrijven) naar Rails-1.2. Nadat ik de vendor/rails map een update naar 1.2 had gegeven werkte de mogelijkheid om documenten te downloaden niet meer. Nu had ik op dat moment direct uit kunnen zoeken wat het probleem vormde en had ik de bug uit de applicatie kunnen halen (wat ik ook gedaan heb), maar bij het tegenkomen van meerdere bugs in de applicatie ben ik tot de volgende werkwijze gekomen om structureel fouten op te sporen in een applicatie welke nog geen testen bevat.

Lees verder...

Geplaatst in ,  | 1 reactie

Server up in een paar minuten met deprec

Geplaatst door Remco van 't Veer do, 01 maa 2007 08:38:00 GMT

Opzoek naar capistrano recepten liep ik een paar dagen geleden tegen deprec aan. Deprec is een setje capistrano recepten om een server productie klaar te maken voor Rails applicaties.

De huidige versie is erg goed in het optuigen van een schone Ubuntu server installatie. Na het draaien van het install_rails_stack recept is de machine verrijkt met Apache 2.2, RubyGems, Rails met dependencies en Mongrel met Mongrel Cluster. Of wel dé Ruby on Rails setup van dit moment.

Maar daar stopt het niet. Deprec kan databases aanmaken en SVN repositories voor je Rails applicatie. Het enige wat je nog op de server hoeft te doen is er je SSH key neer zetten en afentoe apt-get update && apt-get upgrade te draaien.

In de wiki van slicehost staat een uitgebreid artikel over het in productie zetten van een Rails applicatie. En ik sluit me graag bij hen aan “Mike Bailey Earns a Beer”.

Geplaatst in ,  | 2 reacties

assert_select, HTML::Selector en spinnen

Geplaatst door Remco van 't Veer di, 02 jan 2007 19:41:00 GMT

In Rails-1.2 is de assert_tag methode deprecated geworden ipv daarvan hebben we assert_select gekregen. Dat is mooi want van:
assert_tag :tag => 'div', :attributes => {
  :class => 'articles'
}, :descendant => {
  :tag => 'div', :attributes => {
    :id => "article_#{articles(:first).id}"
  }, :descendant => {
    :tag => 'h1'
  }
}
word ik een beetje scheel. De mensen bij W3C hebben een zeer krachtig taaltje ontwikkeld om dit soort selecties te doen, de CSS selectors, en assert_select geeft de mogelijkheid deze taal te gebruiken in functionele en integratie tests:
assert_select "div.articles div#article_%s h1" % articles(:first).id

Ik ben zo enthousiast dat ik zo’n selector ook in m’n test wil gebruiken om links uit m’n HTML te peuteren waarmee ik dan weer andere tests kan doen. Om precies te zijn, ik wil een spider integratie test welke gewoon alle links in m’n applicatie volgt.

Lees verder...

Geplaatst in ,  | 5 reacties

Vriendelijke URI's

Geplaatst door Matthijs Langenberg di, 14 nov 2006 11:38:00 GMT

Al sinds de web-2.Oh hype gestart is worden mooie URL’s als /articles/show/my-first-article en /users/profile/quentin geprefereerd boven /articles/show/324 en /users/profile/1225. Maar er kleven ook grote nadelen aan URL’s als /categories/meat/recipes/chunky-bacon, je stapt in feite van het gebruik van oplopende integers voor primary keys af.

Wat is het nut van je id veld in je articles tabel wanneer je in je URL’s het title veld gebruikt om artikelen de identificeren?

Want wat gebeurd er wanneer een gebruiker de titel van een artikel aan zou passen?

Lees verder...

Geplaatst in ,  | 3 reacties