Archive for the 'introducing' Category

Presenting: The Funkengallery Demo App

Still in beta mode, but we are proud to present a Rails 2.3 application, modularized in plugins, fully I18n (German, English, Swedish), and of course published at github.

This funkengallery demo application includes demonstration of all our plugins:

  • acts_as_category
  • acts_as_identifiable
  • funkengallery
  • funkenlogin
  • funkenlogin
  • irobot
  • manipulify

Again, this is beta still, which means that for example the admin area wants your models to be called exactly “Category” and “User”. So not 100% modularized yet, but we’re getting there and you can already use it as a perfect standalone application ;)

What’s so special about this gallery is the very dynamic user rights management and the simplicity. It is designed for a complex category tree with many thousands of pictures. However, you might expect flickr design and you get… well… funkengallery. It is different and simpler, but really neat if you want to share your pictures quick, private and with individual user rights.

Screenshots and Demo

Check out our Downloads site to see how you can easily test your local demo.

ActiveSupport::Memoizable Cache löschen

Auch wenn es vielen von vorn herein klar ist, mir war es nicht sofort klar :)

Das tolle Memoizable in Rails 2.2 macht das Caching von Methoden einfacher. Ich bin dabei auf eine Frage gestoßen:

Wie lösche ich den Cache?

Als ich mir den Quellcode von Memoizable angeschaut habe, dachte ich auf den ersten Blick, dass memoize_all ALLE Methoden einer Klasse memoizen würde und unmemoize_all alles wieder deaktiviert.

Nun, tatsächlich löscht unmemoize_all nur den gesamten Cache und er wird automatisch mit jedem Aufruf einer Methode Stück für Stück wieder aufgebaut. Wenn man also z. B. eine Änderung vornimmt, sollte man unmemoize_all ausführen.

memoize_all hingegen, führt alle gecachten Methoden auf einmal aus (!) und speichert die Ergebnisse im Cache. Aber das kann doch nicht sein, oder? Kann mir das hier mal jmd. erklären :)

FINALLY! RailsICalendar ical ics publish with ruby on rails

Das hat echt was Nerven gekostet, aber ich bin mehr als zufrieden mit dem Resultat.

Ich darf vorstellen: Wenn man seinen Kalender in Mac OS X (z. B. per Webdav) auf seinen Server lädt (bzw. synchronisiert) und auf diesem Server auch Ruby on Rails läuft, dann kann man seinen Kalender jetzt auf seiner Webseite veröffentlichen.

In fact I just realize I should better speak english, because someone’s German might be somewhat rusty :)

So again: You have ics files on your server (e.g. via webdav) and Ruby on Rails is running? Great, let’s publish your calendar. The idea came from the great PHPicalendar script.

This is what it will somewhat look like:
bild-1.png

I am sorry to not have made a plugin out of this yet, but, hey, the basics are there, help yourself :) If you have any questions feel free to comment.

Requirements:

  • Vpim plugin with sudo gem install vpim

Features:

  • Read several ICS files from a directory on the server
  • Parse all the ical events in them
  • Cache the current calendar in yaml files
  • (The cache will be refreshed when a ICS file was updated meanwhile)
  • HTML will be presented for the calendar
  • Currently you can only choose a date and see the next X days

A word on recurrence of events

  • It does do most of the recurrence rules!
  • Specifically: All that VPIM supports
  • PLUS: EXDATE is also supported!

The Code

Initializer (config/initializers/any_filename.rb)

1
2
3
4
5
# Path to icalendar *.ics files on your server
PATH_ICS       = "#{RAILS_ROOT}/private/calendars/"
PATH_ICS_CACHE = "#{RAILS_ROOT}/tmp/calendars/"
FileUtils::mkdir_p(PATH_ICS)       unless File.exists?(PATH_ICS)
FileUtils::mkdir_p(PATH_ICS_CACHE) unless File.exists?(PATH_ICS_CACHE)

Controller (app/controllers/calendars_controller.rb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
require 'vpim'
class CalendarsController < ApplicationController
 
  def index
    # Load parameters if submitted
    session[:date_year]  = params[:options]["date(1i)"] if !params[:options].blank? && !params[:options]["date(1i)"].empty?
    session[:date_month] = params[:options]["date(2i)"] if !params[:options].blank? && !params[:options]["date(2i)"].empty?
    session[:date_day]   = params[:options]["date(3i)"] if !params[:options].blank? && !params[:options]["date(3i)"].empty?
 
    # Load standard if nothing submitted
    session[:date_year]  = Time.now.year  if session[:date_year].blank?
    session[:date_month] = Time.now.month if session[:date_month].blank?
    session[:date_day]   = Time.now.day   if session[:date_day].blank?
 
    # Set variables
    @scope     = 7
    @events   = []
    @today    = Time.gm(session[:date_year], session[:date_month], session[:date_day])
    cachefile = File.join(PATH_ICS_CACHE, "#{@today.to_s(:ical)}_#{@scope}.yml")
 
    # Kill cache if outdated
    if File.exists?(cachefile)
      killcache = false
      Dir.glob(File.join(PATH_ICS, '*.ics')).each do |file|
        killcache = true if File.mtime(file) > File.mtime(cachefile)
      end
      if killcache
        Dir.glob(File.join(PATH_ICS_CACHE, '*.*')).each do |file|
          File.delete(file)
        end
      end
    end
 
    # Load calendar from cache
    if File.exists?(cachefile)
      @events = YAML.load_file cachefile 
    else
      # No cache, parse each icalendar *.ics file in PATH_ICS and check for event occurences
      Dir.glob(File.join(PATH_ICS, '*.ics')).each do |file|
        category = File.basename(file, '.ics')
        Vpim::Icalendar.decode(File.open(file)).each do |calendar|
          calendar.components do |event|
            for day in 0..@scope
              if start = event.occurs_in?(@today+(60*60*24*day), @today+(60*60*24)+(60*60*24*day))
                myend = start + (event.dtend - event.dtstart)
                @events < < {
                  'category' => category,
                  'day'      => day,
                  'start'    => start,
                  'duration' => ((event.dtend - event.dtstart) / 60).round, # In minutes
                  'end'      => myend,
                  'allday'   => start.hour == 0 && start.min == 0 && start.sec == 0 && myend.hour == 0 && myend.min == 0 && myend.sec == 0,
                  'data'     => event
                }
              end
            end
          end
        end
      end
      @events = @events.uniq # Just in case :)
      # Save cache
      File.open(cachefile, 'w') { |f| YAML.dump(@events, f) }
    end
  end
 
end

Single View (view/calendars/index.html.erb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
< %
  width  = 110      # Width of one day
  height = 6        # height of 15 minutes in pixels
  buffer = 28       # free space for dates in day column (at top of each day)
  minh   = 20       # Minimum of event height
  cutmornings = 120 # I don't have events between 0:00 and 6:00, cut these pixels off
%>
 
<div id="action">
 
< % for day in 0...@scope + 1 do 
  today = (@today+(60*60*24*day))
  case today.wday  
    when 0  
      dayclass = 'class="sunday"'
    when 6  
      dayclass = 'class="saturday"'
    else  
      dayclass = 'class="otherday"'
  end
  %>
  <div id="ical_day" <%= dayclass %>
    style=" width:  < %= width %>px;
            height: < %= height*96 + buffer - cutmornings %>px;
            left:   < %= day*width + day*10 %>px;">
    < % if today.year == Time.now.year && today.month == Time.now.month && today.day == Time.now.day %>
      <b>< %= 'Today' %></b>
    < % else %>
      < %= _(today.strftime("%a")) +', '+ today.to_s(:date) %>
    < % end %>
  </div>
< % end %>
 
< % tops = Array.new(@scope + 1, '')
@events.each do |event|
 
  # Exclude recurrence rule hack
  today = (@today+(60*60*24*event['day']))
  exme = false
  event['data'].propvaluearray('EXDATE').each do |exdate|
    exdate = exdate.to_time
    exme = true if today.year == exdate.year && today.mon == exdate.mon && today.day == exdate.day
  end
  next if exme # Skip this event
 
  if event['allday']
    # All-day events will be inserted later
    tops[event['day']] += '&nbsp; ' + event['data'].summary.to_s + '<br/>'
  else 
    eventheight = ((event['duration']/15)*height).round
    eventheight = minh if eventheight < minh
    %>
    <div id="ical_event"
      style=" background: #<%= eventcolor(event['category']) %>;
              width:  < %= width-2 %>px;
              height: < %= eventheight.to_s %>px;
              top:    < %= event['start'].hour*height*4 + (event['start'].min/15)*6 + buffer - cutmornings %>px;
              left:   < %= event['day']*width + event['day']*10 %>px;">
      < %= '<b>'+ event['start'].to_s(:time) +' - '+ event['end'].to_s(:time) +'<br />' %>
      < %= event['data'].summary %>
    </div>
  < % end %>
< % end %>
 
< % tops.each_with_index do |top, day| %>
    <div id="ical_event_top"
      style=" width: <%= width-2 %>px;
              height: < %= height %>px;
              top: < %= buffer %>px;
              left: < %= day * width + day * 10 %>px;">
      < %= top %>
    </div>
< % end %>
 
<div id="vertical_spacer" style="height: <%= height*96 + buffer*2 - cutmornings %>px;">&nbsp;</div>
 
</div>

Layout View (views/layouts/calendars.html.erb)

        < % form_tag :controller => 'calendars', :action => nil, :id => nil do |f| %>
          < %= date_select("options", "date", :default => @today, :order => [:day, :month, :year]) %>
            < %= submit_tag 'Show' + ' &raquo;', :class => 'date_button' %>
        < % end %>

Helper (for coloring events) (app/helpers/calendar_helper.rb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module CalendarsHelper
 
  def eventcolor(category)
    case category  
      when 'Wichtig'   # This is the name of the .ics file
        return 'f66'
      when 'Sonstiges'
        return '4f4'
      when 'Studium'
        return 'fb4'
      when 'Privat'
        return '77f'
      when 'Freunde'
        return 'f4f'
      else  
        return 'fb4'
    end
  end
 
end

Stylesheet (public/stylesheets/calendar.css)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**************** DIVs ***************************/
 
div#action {
  position: absolute;
  margin-left: 10px;
  margin-top: 10px;
  padding: 4px;
  border-left: 0px;
}
 
div#ical_day {
  position: absolute;
  padding-top: 5px;
  text-align: center;
  font-size: 10px;
}
 
.otherday {
  background: #ddd;
}
 
.sunday {
  background: #fdd;
}
 
.saturday {
  background: #ddf;
}
 
#ical_event {
  position: absolute;
  border: 1px #555 solid;
  background: #fb4;
  font-size: 8px;
  text-align: left;
}
 
#ical_event_top {
  position: absolute;
  border: 0px;
  font-size: 9px;
  font-weight: bold;
  text-align: left;
}
 
/**************** Fonts ***************************/
 
#title {
  float:right;
  color: #ddd;
  margin-top: 30px;
  margin-right: 10px;
  line-height: 11px;
  font-size: 16px;
  text-align: right;
}
#title .description {
  color: #777;
  font-size: 10px;
  margin: 0;
}

Routes (could be optional) (config/routes.rb)

1
2
  # CALENDAR Controllers
  map.connect 'calendar', :controller => 'calendars'

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!

MCV Ruby on Rails – was gehört wohin?

Model, Controller, View oder Helper?

Die Kommentare zu diesem Post stellen eine Diskussion über die Funktionen der Hauptbereiche von Ruby on Rails dar. Das Ergebnis wird dann hier zusammengefasst.

Es ist auch klar, dass die Unterteilung der Bereiche nicht eindeutig ist, aber vielleicht finden wir eine gute Tendenz.

HowTo: MySQL 5, Mongrel, Capistrano + Subversion

Update: Bis her war ein Fehler in diesem HowTo. MySQL muss natürlich als Server Version installiert werden ($ sudo port install mysql5 +server). Das Update betrifft nur den MySQL5 Bereich.

Damit wir Ruby on Rails auch wirklich nutzen können, sollten wir noch ein paar Programme, Tools und Gems installieren.

Als erstes wäre da MySQL, denn wie wollen wir Datenbankgestütze Webentwicklung betreiben, wenn wir nicht mal einen Datenbank-Server und damit eine Datenbank haben…

MySQL5
Da wir ja MacPorts installiert haben ist das ganze recht einfach. Um auf Nummer Sicher zu gehen, machen wir jedoch erst mal ein selfupdate für MacPorts und installieren erst dann MySQL5

$ sudo port selfupdate
$ sudo port install mysql5 +server
$ sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
$ sudo chown -R mysql:mysql /usr/local/macports/var/db/mysql5
$ sudo -u mysql mysql_install_db5

Jetzt am besten den Mac neu starten, dann kann man gleich sehen ob das LauchItem funktioniert.

MySQL Native Bindings Gem
Jetzt kommt der Teil, der mich die meiste Zeit gekostet hat (dabei sollte er doch die Geschwindigkeit der MySQL Abfragen beschleunigen) und der Grund war, warum ich bis her ohne die Nativen Bindings auskommen musste.
Das MySQL Gem ist irgendwie sehr unflexible, was die Pfade angeht und dazu kommt, dass MacPorts die MySQL Installation im MacPorts Verzeichnis nicht gebündelt ablegt sondern etwas zerfledert… anstelle eines einfachen gem install mysql war hier etwas mehr Finetuning nötig. Mittels der build-flags gelang mir dann aber auch das. Hier das Ergebnis:

sudo gem install mysql -- \
--with-mysql-dir=/usr/local/macports/lib/mysql5 \
--with-mysql-lib=/usr/local/macports/lib/mysql5/mysql \
--with-mysql-include=/usr/local/macports/include/mysql5/mysql

NACHTRAG, ab November 2008 so:

sudo env ARCHFLAGS="-arch ppc" gem install mysql -- --with-mysql-lib=/opt/local/lib/mysql5/mysql --with-mysql-include=/opt/local/include/mysql5/mysql

jetzt wird man gefragt, welche Version man für die Installation wählen will. Nehmen wir also die neuste, zum jetzigen Zeitpunkt mysql 2.7 (ruby), also drücken wir die 3 (da wir uns ja auf einem Mac befinden fallen die mswin32 Versionen für uns raus)

Select which gem to install for your platform (i686-darwin8.10.3)
1. mysql 2.7.3 (mswin32)
2. mysql 2.7.1 (mswin32)
3. mysql 2.7 (ruby)
4. mysql 2.6 (ruby)
5. Skip this gem
6. Cancel installation

Wenn man die build-flags nicht richtig setzt bekommt man solche Fehler:

ERROR: Failed to build gem native extension.
ruby extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no

und kann damit nicht so wirklich was anfangen… wie gesagt hat mich einiges an Zeit gekostet, weil auch Google dazu nicht richtig was sagt.

So nun sind auch die Bindings fertig und wir können uns anderen Dingen zuwenden.

Mongrel
Mongrel ist der Webserver. Rails liefert zwar schon einen Webserver mit (Webrick) aber Mongrel hat für mich bis her einen sehr sehr großen Vorteil, man sieht im Development Mode alle Requests. Damit fällt das Debugging viel leichter, da man sogar die MySQL Requests mit allen Werten sieht. Also installieren wir das Mongrel Gem einfach.

sudo gem install mongrel --include-dependencies

es kommen wieder die von oben bekannten Abfragen zur Version und weil es Abhängigkeiten gibt, die erfüllt werden müssen, wird gleich noch fastthread installiert. Meine Versionen sind mongrel 1.0.1 (2 drücken) und fastthread 1.0 (1 drücken).

Select which gem to install for your platform (i686-darwin8.10.3)
1. mongrel 1.0.1 (mswin32)
2. mongrel 1.0.1 (ruby)
3. mongrel 1.0 (mswin32)
4. mongrel 1.0 (ruby)
5. Skip this gem
6. Cancel installation
> 2
Select which gem to install for your platform (i686-darwin8.10.3)
1. fastthread 1.0 (ruby)
2. fastthread 1.0 (mswin32)
3. fastthread 0.6.4.1 (mswin32)
4. fastthread 0.6.4.1 (ruby)
5. Skip this gem
6. Cancel installation
> 1

Gut damit haben wir neben dem MySQL-Server nun auch unseren Webserver. Was jetzt kommt ist erst mal nicht so wichtig aber wir installieren es mal, damit wir uns später keine Gedanken mehr drum machen müssen.

Capistrano
Capistrano ist ein Deployment Tool, was einem die Arbeit des live gehens erheblich erleichtern soll. Ich hab es noch nicht benutzt und genau deshalb installiere ich es jetzt mit um es in den nächsten Tagen zu testen. Darüber wird es dann auch einen Post geben.
Neben dem hoch laden der Dateien mittels SSH, kann man noch eigene Rake Tasks in Ruby schreiben, die dann z.B. einen Dump der alten Datenbank erstellen, bevor die neue eingespielt wird. Naja wie gesagt, bei mehr Erfahrungen gibt es auch dazu einen Post, jetzt erst mal die Installation:

sudo gem install capistrano --include-dependencies

Jetzt noch Termios, dass dafür sorgen soll, dass die Passwörter, die man in Capistrano eintippt, nicht von allen gelesen werden können. Ich weiß nicht, ob das notwendig ist aber weh tun tut es ja auch nicht also:

sudo gem install termios --include-dependencies

Subversion
Subversion ist auch so nen Ding, worüber alle reden, was ich aber bis zum jetzigen Zeitpunkt, außer für Plugin Installationen, nicht genutzt habe. Capistrano nutzt es auch, also installieren wir auch noch dieses Tool. Eigentlich ist es einfach eine Versionskontrolle und wird meistens eingesetzt, wenn man in einem Team programmiert (es zeigt einem Konflikte an, d.h. zwei Leute haben zur gleichen Zeit an einer Datei, den selben Teil verändert, jeder natürlich anders und die Änderungen würden verlohren gehen. Hier springt dann eben SVN ein und man kann den Konflikt auflösen.)

sudo port install subversion

So damit haben wir eigentlich erst mal alles, was wir für die Entwicklung mit Ruby on Rails brauchen. Wenn es noch irgendwelche Sachen gibt, die man unbedingt braucht ab in die Kommentare damit.

ÜÄÖß Umlaute kaputt in Ruby on Rails und MySQL [broken umlauts]

Hier die Lösung, wenn nur “??” für sämtliche Sonderzeichen ausgegeben wird in Ruby on Rails (wenn man Standardeinstellungen verwendet):

Update: Klaus hat in den Kommentaren eine bessere Lösung vorgeschlagen:
Einfach den Entwicklungsstadien (development, test, production) encoding: utf8 zufügen. Sieht dann so aus:
projekt/config/database.yml

development:
  adapter: mysql
  database: projekt_development
  username: root
  password:
  socket: /tmp/mysql.sock
  encoding: utf8
test:
  adapter: mysql
  database: projekt_test
  username: root
  password:
  socket: /tmp/mysql.sock
  encoding: utf8
production:
  adapter: mysql
  database: projekt_production
  username: root
  password:
  socket: /tmp/mysql.sock
  encoding: utf8

Hier die veraltete Lösung:

class ApplicationController < ActionController::Base
  before_filter :configure_charsets
  private
  def configure_charsets
    @response.headers["Content-Type"] = "text/html; charset=utf-8"
    # Nur ab MySQL 4.1
    suppress(ActiveRecord::StatementInvalid) do
    ActiveRecord::Base.connection.execute 'SET NAMES UTF8'
  end
end

HowTo: Ruby on Rails via MacPorts (aka DarvinPorts) unter Mac OS X

Auch wenn es über die Installation von Ruby on Rails schon viele Posts gibt, habe ich mich entschlossen noch einen zu schreiben. Meistens fehlen mir bei diesen Anleitungen kleine Details und ich denke, dass es besonders für Mac OS X Neulinge, bzw. Menschen, die sich auf der Kommandozeile nicht so auskennen, etwas schwer nach zu voll ziehen ist, was sie da überhaupt gerade machen.

Zum anderen, soll dieses Blog auch ein wenig unsere Entwicklung, die wir mit Ruby on Rails durch mache, wieder spiegeln und da ist es doch ganz gut, wenn man ganz von Vorne beginnt.

Jetzt gibt es erst mal eine Kurzanleitung mit allen nötigen Befehlen, für die Leute, die Ruby on Rails einfach nur ganz schnell installieren wollen und keinen Text mögen. Falls es dann zu Problemen kommt, müsst ihr halt doch noch mal unten schauen ;-).

Zusammenfassung
Source Dateien von der MacPorts Seite laden

$ tar -xvzf MacPorts-1.5.0.tar.gz
$ cd MacPorts-1.5.0
$ ./configure --prefix=/usr/local/macports
$ make
$ sudo make install
$ sudo ln -s /usr/local/macports/bin/port /usr/bin/port
$ cat >>~/.profile
PATH=/usr/local/macports/bin:$PATH ; export PATH
ctrl+D drücken
$ PATH=/usr/local/macports/bin:$PATH ; export PATH
$ sudo port selfupdate
$ sudo port install rb-rubygems
$ gem update
$ sudo gem install rails --include-dependencies
$ rails -v

Update Michael schreibt in den Kommentaren, dass bei Mac Ports 1.6.0 vor $ sudo gem install rails –include-dependencies noch ein $ sudo port install rb-rails kommen muss.

MacPorts

MacPorts (ehemals DarvinPorts) ist ein Packet Management System, wie es eigentlich fast jedes Unix System hat, das es einem erleichtert Programme zu installieren und sie auf dem aktuellen Stand zu halten. Das System berücksichtigt und installiert auch alle Abhängichkeiten, d.h. alle Programme und Bibliotheken, die für das zu installierende Programm benötigt werden. Um bereits Installierte Versionen von Ruby oder anderen Sachen, muss man sich keine Sorgen machen, da die MacPorts Installationen abgeschottet davon liegen und sich nicht beeinflussen.

Um MacPorts und später Ruby on Rails zu installieren, muss man

  • als Administrator eingelogged sein, um das SuperUser Command sudo ausführen zu können (wird später noch ganz oft gebraucht)
  • Xcode Tools installiert haben (sind auf der OS X CD oder bei Apple, auf jeden Fall mal checken, ob das auf der CD die Aktuelle Version ist. Geht ganz einfach in dem man in die About Xcode Tools.pdf rein schaut, da steht die Version drin. Gerade is das 2.4.1)

MacPorts gibt es mitlerweile auch mit einem Installer aber ich möchte es hier einmal selber kompilieren um es gesammelt unter /usr/local/macports zu haben. So kann man es jeder Zeit ohne Probleme wieder löschen, in dem man einfach den Ordner löscht.

Also als erstes müssen wir uns die Source Dateien auf den Desktop runter laden (einfach die aktuellste Version wählen, zum jetzigen Zeitpunkt ist das 1.5.0), ich nutze die MacPorts-1.5.0.tar.gz. Dann entpacken wir das ganze. Dazu gehen wir ins Terminal (zu finden unter Programme -> Dienstprogramme -> Terminal, das ist die Kommandozeile auf der wir uns jetzt die ganze Zeit bewegen werden) und tippen ein paar Befehl ein. Für all, die noch nie mit dem Terminal gearbeitet haben hier noch ein paar Hinweise:

  • das $ signalisiert nur, dass es sich um die Kommandozeile handelt, der Befehl fängt erst danach an
  • mit dem Tabulator kann man Dateien oder Pfade vervollständigen lassen, bzw. sich die Möglichkeiten anzeigen lassen (Beispiel $ cd Des tippen und dann den Tabulator drücken führt zu $ cd Desktop)

Also los:

$ cd Desktop
$ tar -xvzf MacPorts-1.5.0.tar.gz

Es wird die Liste mit den entpackten Files angezeigt. Wir wechseln nun in das neue Verzeichnis und führen das ./configure Script mit dem Prefix, in das wir MacPorts installieren wollen aus. Dadurch wird die Installation vorbereitet (man sieht einen Haufen Tests die das Script ausführt. Wenn ein “WARNING: X11 not available.” auftaucht, ist das nicht weiter schlimm, da wir keine X11 Pakete installieren wollen). Im Anschluss kompilieren wir MacPorts mit dem Befehl “make” und installieren es mit “sudo make install”, hier werden wir nach dem Administrator Kennwort gefragt, einfach eintippen und den Mac arbeiten lassen.

$ cd MacPorts-1.5.0
$ ./configure --prefix=/usr/local/macports
$ make
$ sudo make install

Das Gröbste wäre damit erledigt. Wir legen noch einen Symlink an, um uns die weitere Arbeit zu erleichtern und nicht immer den ganzen Pfad eingeben zu müssen.
Damit die alte Ruby Version nicht mehr benutzt wird und irgendwann Probleme machen könnte, ändern wir noch $PATH, indem wir eine .profile Datei erstellen, in die wir den MacPorts installations Pfad aufnehmen. Damit das ganze auch gleich funktioniert (normal müssten wir uns neu einloggen) ändern wir $PATH gleich noch für diese Session.
Danach machen wir noch ein selfupdate für MacPorts, hier holt sich MacPorts alles was es braucht und macht ggf. noch ein Update (kann also ein bisschen dauern)

$ sudo ln -s /usr/local/macports/bin/port /usr/bin/port
$ cat >>~/.profile
PATH=/usr/local/macports/bin:$PATH ; export PATH
ctrl+D drücken
$ PATH=/usr/local/macports/bin:$PATH ; export PATH
$ sudo port selfupdate

Ein einfaches

$ sudo port install rb-rubygems

installiert uns jetzt die RubyGems mit denen wir nun mit der eigentlichen Ruby on Rails Installation anfangen können. Die Installation von RubyGems kann eine ganze Weile dauern, da ja auch alle Abhängigkeiten installiert werden müssen, also wenn du ein Raucher bist: Zurück lehnen, Mukke laufen lassen und die Kippe anmachen…

Ruby on Rails

Als erstes sollten wir nun ein Update der gems machen und dann Rails mit all seinen Abhängichkeiten installieren. Das kann je nach Mac und Server Status auch wieder ewig dauern… noch ne Kippe? (Machmal spackt der http://gems.rubyforge.org Server rum und sagt, dass er die Pakete nicht lesen kann. Bei mir hat ein gem query –remote geholfen, dass alle verfügbaren Pakete anzeigt. Danach ging der normale install Befehl… kann auch nur Zufall gewesen sein ;-))


$ gem update
$ sudo gem install rails --include-dependencies

Update:
In den Kommentaren hat Phil darauf hingewiesen dass es hier zu einem Problem beim $ gem update kommen kann. Seine Lösung sieht ein

$ sudo port -ufn upgrade rb-rubygems

vor dem $ gem update vor. (Quelle: http://lists.macosforge.org/pipermail/macports-dev/2007-June.txt)

Danke Phil!

So das war es, Rails ist nun installiert! Herzlichen Glückwunsch erst mal =)

Hier noch ein paar checks

$ rails -v
$ ruby -v
$ which rails
$ which ruby

sollte ungefähr das hier ausgeben (je nachdem welche Version du hast):
Rails 1.2.3
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.3]
/usr/local/macports/bin/rails
/usr/local/macports/bin/ruby
Wichtig ist hier, dass die beiden Pfade das MacPorts Verzeichnis beinhalten.

Jetzt gibt es noch nen paar Gems, die man installieren sollte aber darauf gehe ich in weiteren Posts genauer ein.