Archive for the 'ruby on rails' Category

Page 2 of 3

cap deploy “permission denied” nach upgrade auf capistrano 2.1

Hier habe ich endlich gefunden wieso aus heiterem Himmel bei einem cap deploy mit ssh und svn (und public key authentication) immer folgender Fehler auftrat:

** [err] Permission denied, please try again.
** [err] Permission denied, please try again.
** [err] Permission denied (publickey,password).
** [err] svn: Netzwerkverbindung wurde unerwartet geschlossen

In die /config/deploy.rb muss folgende Option mit aufgenommen werden:

default_run_options[:pty] = true

Wenn ihr wissen wollt wieso, müsst ihr im original Beitrag nachschauen. Es hat mit den Rechten bei der shell zu tun und jetzt werden auch die user profile auf dem server vorher geladen.

gem1.8 install mysql (MySql Ruby C bindings) in debian

Hier habe ich endlich gefunden, wieso genau die C Bindings für mysql nicht geklappt haben. Es fehlte noch ein apt Paket vorher (bzw. ich benutze aptitude).

Hier lag des Rätsels Lösung:

aptitude install libmysqlclient15-dev

Und erst dann hat man die mysql_config wie folgt zur Hand:

gem1.8 install mysql — –with-mysql-config=/usr/bin/mysql_config

Wie gesagt, “aptitude” muss für den ein oder anderen “apt get” sein und wenn man nicht als root eingeloggt ist, kommt noch ein “sudo” vor jeden Befehl.

Hinweis: Welches Paket man sich mit apt installieren muss (dieser Post muss ja nicht der aktuellste sein ;), kann man mit diesem Befehl herausfinden. Dann nimmt man einfach die neuste Version von dem oben genannten.

aptitude show libmysql

Sessions aufräumen – Stale Sessions Clean Up

Wenn man den ganz normalen Session Handler von Rails benutzt, dann werden die Sessions unter tmp/sessions/ abgelegt. Rails räumt dieses Session Verzeichnis aber nicht selber auf. Das kann zu einem Problem werden, wenn man plötzlich tausende von Sessionfiles in diesem Verzeichnis findet. Erst einmal wird die Application dadurch langsamer und zum Zweiten kann es auch das File System des Servers belasten, wenn der nämlich plötzlich keine Nodes mehr machen kann.

Eine einfach Lösung für dieses Problem ist ein Cron Job der das Verzeichnis regelmäßig aufräumt und alle alten (stale) Sessions löscht.

Hierfür habe ich ein Shell Script geschrieben, was ich in den Script Ordner meines Rails Projektes abgelegt habe. So sieht es aus:
script/remove_stale_sessions.sh

#!/bin/sh
find ../tmp/sessions/ruby_sess.* -mtime +1 -print | xargs rm -rf

Das Script löscht alle Sessions die seit 1 Tag nicht mehr benutzt wurden. Jetzt fehlt noch der Cron Job, der das Script alle paar Minuten aufruft. Ich hab ihn mal auf alle 10 Minuten gestellt. Mit crontab -e ruft man den Cron Job Manager auf. Jetzt i drücken, damit man in den INSERT Mode kommt und in die letzte Zeile folgenden Code schreiben:

*/10 * * * * sh /pfad/zur/app/script/remove_stale_sessions.sh

esc drücken um den INSERT Mode zu verlassen und :wq zum speichern und schon sollte der neue Cron installiert sein.

Update:
Ach so… vielleicht sollte man dafür gleich nen Deployment Task oder so was schreiben… irgendwas, damit man halt nicht bei jedem Projekt dran denken muss… wenn jemand Vorschläge hat…

Localization Plugin: Improved generate_l10n_file

Das Localization Plugin hat eine Methode generate_l10n_file um die zu lokalisierenden Strings auszulesen. Leider macht sie dies nicht besonders gut.

Auf die Schnelle habe ich sie etwas abgeändert und siehe da:

def self.generate_l10n_file
  "Localization.define('de') do |l|" < <
  Dir.glob("#{RAILS_ROOT}/app/**/*.*").collect do |f| 
    ["# #{f}"] << File.read(f).scan(/(<%=_ |_\()[\"\'](.*?)[\"\']/)
  end.uniq.flatten.collect do |g|
    g.starts_with?('#') ? "" : "  l.store '#{g}', ''"
  end.uniq.sort.join("\n").gsub("  l.store '_(', ''",'').gsub("  l.store '<%=_ ', ''",'') << "\nend"
end

Jetzt werden sämtliche Controller ausgelesen und es werden deutlich mehr Strings gefunden (nämlich auch die wo nicht %= davor steht).

UPDATE: Zu “#{RAILS_ROOT}/app/**/*.*” müsste man noch “#{RAILS_ROOT}/app/views/**/*.*” irgendwie hinzunehmen.

Hier noch ein rake task dafür:

namespace [:l10n] do
    desc 'Verbose localization file (experimental)'
    task :generate => :environment do
      puts
      puts 'Creating localization file...'
      puts '----------- SNIP -----------'
      puts Localization.generate_l10n_file
      puts '----------- SNAP -----------'
      puts
      puts 'Finished.'
      puts
    end
end

“Capistrano überschreibt meine Dateien immer!”

Wer seit Neuestem mit Capistrano seine rails app deployed, der kam vielleicht auch schon dahinter, dass dann alle Dateien weg sind, die man in ein bestimmtes Verzeichnis geschrieben oder hochgeladen hat.

“meinprojekt” ist im Folgenden das Verzeichnis auf dem Server, wohin deployed wurde. Standardmäßig ist das glaube ich /u/apps/meinprojekt.

Also zum Beispiel meinprojekt/public/uploads wird nach dem deploy einfach gelöscht und alle Dateien sind weg (nicht wirklich weg, man muss nur im Verzeichnis meinprojekt/releases danach suchen ;).

Um das zu verhindern (hier gefunden) muss man im meinprojekt/shared Verzeichnis auf dem Server wo man es deployed hat die Verzeichnisse erstellen, die solche wichtigen Sachen enthalten.

Also z. B. mkdir meinprojekt/shared/public/uploads. Anschließend passt man seine deploy.rb wie folgt an:

task :after_update_code, :roles => :app do
run “ln -nfs #{deploy_to}/shared/public/uploads #{release_path}/public/uploads”
end

Dadurch wird nachdem der Code deployed (also hochgeladen) wurde, ein Hardlink von dem deployten uploads-Verzeichnis auf /u/apps/meinprojekt/shared/public/uploads gemacht. Also sozusagen ein weiterverweisen auf das shared Verzeichnis.

Immer wenn jetzt jemand was hochläd, wird es in shared gespeichert, anstatt in current. Beim nächsten Deploy wird der Link wieder auf shared gesetzt und keine Daten gehen verloren.

Hier mal ein Beispiel für meine Gallery:

namespace :deploy do
[task :start...]
after “deploy:update_code”, :link_to_shared
end

# Create hard links to data in shared
desc “Link in critical data”
task :link_to_shared do
run “ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml”
run “ln -nfs #{deploy_to}/shared/backup #{release_path}/backup”
run “ln -nfs #{deploy_to}/shared/private #{release_path}/private”
run “ln -nfs #{deploy_to}/shared/public/images/gallery #{release_path}/public/images/gallery”
run “ln -nfs #{deploy_to}/shared/public/images/pending #{release_path}/public/images/pending”
end

Super. Danke Capistrano 2, dass du das kannst :)

Plugin: acts_as_list_in_tree und descendants in acts_as_tree

Ich habe eine Kategorienliste mit Unterkategorien. Nun möchte ich acts_as_list verwenden, um die Reihenfolge mit den Feld “position” leichter ändern zu können. Das geht auch soweit (Dann hat man so tolle Funktionen wie Category.move_higher).

Leider gibt es da aber immer wieder Probleme, da eine neu hinzugefügte Kategorie die Position max(alle_positionen)+1 erhält. Also die höchste ALLER Positionen +1. Ich möchte aber, dass eine neu hinzugefügte Kategorie die position+1 bezogen auf seine Vaterkategorie erhält!

Also sich als Liste verhält, aber nur in Bezug auf seine Geschwister!

Dafür muss man das Plugin (Rails 2.0) “acts_as_list” ändern. Und zwar muss man die Zeile 64, auskommentieren:

##{scope_condition_method}

Und die Funktion scope_condition() in Zeile 186 wie folgt ändern:

# Overwrite this method to define the scope of the list changes
#def scope_condition() "1" end
def scope_condition() "parent_id = #{self.parent_id}" end

So habe ich mir mein eigenes acts_as_list_in_tree (download) Plugin gebaut.

Vielleicht noch als Anmerkung:
In acts_as_tree gibt es KEINE DESCENDANTS Funktion! Das heißt, man kann sich in einem Tree nicht die Nachkommen ausgeben lassen. Die Vorfahren schon, mit .ancestors, aber halt nicht die Nachkommen.

Siehe da HIER habe ich die Lösung gefunden. Ich hatte nur gehofft, sie sei in Rails 2.0 schon implementiert, ist sie aber nicht!

Also selber hinzufügen (am besten unter die ancestors funktion) in
/vendor/plugins/acts_as_tree/lib/active_record/acts/tree.rb:

# Bugfix - Returns list of descendants
def descendants 
  descendants = [] 
  self.children.each { |child| descendants += [child] + child.descendants } if self.children.length > 0 
  descendants
end

Wenn es in Rails 2.x übernommen wird, kann man es wieder löschen ;)

Das war’s für heute :)

BasicAuth + ProxyPath (Apache + Mongrel)

Ich bin gerade dabei ein Rails Projekt mit Apache und Mongrel zum laufen zu bringen.
Das ganze soll aber erst mal hinter nem htaccess Passwort Schutz sein. Ich hab nun Ewigkeiten gesucht um das hin zu bekommen, denn wenn ich es einfach in die .htaccess im public Verzeichnis meines Rails Projektes ablege, geht es natürlich nicht, da die BasicAuth ja vom Apache gemacht wird und der hat die Anfrage ja schon an Mongrel übergeben…

Das ganze ist aber eigentlich recht einfach. Jetzt steht der BasicAuth Code im vhost drin und das sieht dann so aus:

<proxy *>
AuthName “Nur mit Passwort”
AuthType Basic
AuthUserFile /pfad/zur/.htpasswd
require valid-user
</proxy>

ProxyRequests Off
ProxyPreserveHost On

ProxyPass / http://0.0.0.0:3000/
ProxyPassReverse / http://0.0.0.0:3000/
ErrorLog /pfad/zum/server.log

wichtig war die Direktive <proxy *> in der der BasicAuth Code stehen muss. Sonst wird es einfach ignoriert!

Update:
Und so wird es dann in Rails 2.0 gemacht: HTTP Basic Authentication

HowTo: ImageMagick + RMagick via Macports für Tiger

Nach dem ich nun auch RMagick für ein aktuelles Projekt brauchte, dachte ich ich nehm einfach die Anleitung von hier (ok steht ja schon im Posttitel ist für Leopard und nicht für Tiger) Das hat natürlich nicht funktioniert und mich min. 2 h gekostet. Deshalb hier die Anleitung für Mac OS X Tiger:

Dauert ewig, für ImageMagick wird erst mal das ganze XFree86 Zeug und noch sonstige Sachen runter geladen. RMagick muss dann noch die ganzen Fonts einbinden, das dauert auch…


sudo port install ImageMagick
sudo port install libwmf
sudo port install lcms
sudo port install ghostscript
sudo gem install rmagick -y

Das Problem war einfach, dass die 3 anderen Port-Installationen gefehlt haben. Ich glaub es lag eigentlich nur an der fehlenden ghostscript Installation.

Dank geht hier noch hin, da gab es die Lösung.

Railscasts.com – die beste Ruby on Rails Resource

Auch wenn es die meisten wohl schon kennen, die Screencasts von Ryan Bates, sind meiner Meinung nach, so ziemlich die beste Resource, was praktische Tipps mit Ruby on Rails angeht. Er spricht so ziemlich alle wichtigen Themen an und bietet auch für etwas erfahrenere Entwickler manch eine Idee.
Also unbedingt anschauen, wer es noch nicht kennt:
www.railscasts.com

Ruby on Rails with Leopard (localhost, sites, mysql, rmagick)

Ich habe soeben 2 Minuten gebraucht, um intuitiv Rails in Leopard zum Laufen zu kriegen…

Das möchte ich euch natürlich nicht vorenthalten.

Du wechselst in das Verzeichnis deines Projektes.

bild-5.png

Und gibst den Befehl ruby script/server ein.

bild-6.png

Ergebnis:

bild-7.png

Fertig!

“Mongrel available at 0.0.0.0:3000″ verrät dir, wo du deine Webseite findest. Da “0.0.0.0″ das gleiche ist wie “localhost”, findest du sie z. B. hier:

bild-8.png

Mist war das einfach :/

MySQL

HIER könnt ihr mysql runterladen. Kleiner Tip: Intel-Rechner brauchen “x86″. Mein PowerBook G4 hat Mac OS X 10.4 (PowerPC, 32-bit) gebraucht.

Package installieren, fertig. Vorsicht, momentan funktioniert das prefpane von mysql in den Systemeinstellungen für Leopard nicht. Das kann man beheben, indem man dem Verzeichnis /usr/local/mysql/data UND UNTERVERZEICHNISSEN Lese- und Schreibrechte für Administratoren (oder halt direkt dir selbst) hinzufügt. Wie geht das? Einen invisibility toggler runterladen und alle Dateien im Finder sichtbar machen. Auf das Verzeichnis ein “Apfel + i” machen und ganz unten die Reche entsprechend hinzufügen.

Nachdem ich jetzt zwei Tage versucht habe einen “sudo gem install mysql” durchzuführen, kam ich endlich auf die Lösung. (Danke an rubyonrails.org die schnell genug waren. Hier auch nochmal ausführlich.

Kurzum, folgenden langen Befehl im Terminal eingeben:

sudo env ARCHFLAGS="-arch ppc" gem install mysql — –with-mysql-config=/usr/local/mysql/bin/mysql_config

Dort wo “ppc” steht muss nicht ppc sondern i386 heißen, wenn ihr einen Intel-Prozessor habt (MacBook usw.)

mysqlok.png

Wenn ihr nur sudo gem install mysql oder sudo gem install mysql — –with-mysql-dir=/usr/local/mysql macht, dann kommt ein “can’t find ruby header” Fehler. Danach habe ich gegoogled ohne Ende und nichts gefunden.

Übrigens kann nun ein sudo gem update rails nicht schaden, das updated ein paar gem versionen.

Wie man mit MacPort RMagick installiert, ist hier schön beschrieben.

Fertig!