Rails Tutorial DHBW-Heidenheim | ||
Anwendung erzeugenEine neue Anwendung wird mit rails new [name] erzeugt. Dabei werden eine Reihe von Verzeichnissen und Dateien angelegt. noname:rs till$ rails new Beispiel -d mysql create create README create Rakefile create config.ru create .gitignore create Gemfile create app create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/mailers create app/models create app/views/layouts/application.html.erb create config create config/routes.rb create config/application.rb create config/environment.rb create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb create config/initializers create config/initializers/backtrace_silencers.rb create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/initializers/secret_token.rb create config/initializers/session_store.rb create config/locales create config/locales/en.yml create config/boot.rb create config/database.yml create db create db/seeds.rb create doc create doc/README_FOR_APP create lib create lib/tasks create lib/tasks/.gitkeep create log create log/server.log create log/production.log create log/development.log create log/test.log create public create public/404.html create public/422.html create public/500.html create public/favicon.ico create public/index.html create public/robots.txt create public/images create public/images/rails.png create public/stylesheets create public/stylesheets/.gitkeep create public/javascripts create public/javascripts/application.js create public/javascripts/controls.js create public/javascripts/dragdrop.js create public/javascripts/effects.js create public/javascripts/prototype.js create public/javascripts/rails.js create script create script/rails create test create test/fixtures create test/functional create test/integration create test/performance/browsing_test.rb create test/test_helper.rb create test/unit create tmp create tmp/sessions create tmp/sockets create tmp/cache create tmp/pids create vendor/plugins create vendor/plugins/.gitkeep noname:rs till$ Gestartet wird die Anwendung mit dem Befehl rails server. Dieser startet einen Webserver, der als default den Port 3000 verwendet. Dort ist die Anwendung verfügbar. noname:rs till$ cd Beispiel noname:Beispiel till$ rails server => Booting WEBrick => Rails 3.0.3 application starting in development on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server [2011-01-24 11:33:03] INFO WEBrick 1.3.1 [2011-01-24 11:33:03] INFO ruby 1.8.7 (2009-06-12) [universal-darwin10.0] [2011-01-24 11:33:03] INFO WEBrick::HTTPServer#start: pid=9744 port=3000 Ruft man nun diese Anwendung im Browser auf, wird eine default Seite angezeigt (die natürlich geändert werden kann. Es handelt sich hier um die Datei index.html im Unterverzeichnis public).
Datenbank konfigurierenVerwendet man eine sqlite Datenbank (bei rails new keinen Datenbank-Parameter angeben) ist dieser Schritt nicht nötig. Soll eine andere Datenbank verwendet werden - hier im Beispiel mysql - muss die Datenbank-Konfiguration angepasst werden. Insbesondere müssen die Anmeldeinformationen für den Datenbankserver angegeben werden. Diese Informationen stehen in der Datei database.yml im Unterverzeichnis config. Hier müssen normalerweise die entsprechenden Eintr&aum;ge gemacht werden. Für unser Beispiel braucht hier nichts geändert zu werden, da rails als default den Benutzer root ohne Kennwort einträgt. In unserem Beispielsystem ist dies korrekt, in einem "echten" System hätte der Benutzer root vermutlich ein Kennwort. # MySQL. Versions 4.1 and 5.0 are recommended. # # Install the MySQL driver: # gem install mysql2 # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html development: adapter: mysql2 encoding: utf8 reconnect: false database: Beispiel_development pool: 5 username: root password: host: localhost In einem produktiven System müssten hier ggf. Einträge angepasst werden. Im folgenden Abschnitt ist eine solche Konfiguration gezeigt. Hier ist auch noch der socket Parameter gesetzt. Als default wird hier /tmp/mysql.sock verwendet. Dies funktioniert unter MAC OS X nicht, hier ist dieser socket üblicherweise im Verzeichnis /var/mysql zu finden. Achten Sie darauf, auch die Einträge in den Abschnitten test und production anzupassen. rails erzeugt drei Datenbanken, eine für die Entwicklung, eine für den Test und eine für den Betrieb. # MySQL. Versions 4.1 and 5.0 are recommended. # # Install the MySQL driver: # gem install mysql2 # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html development: adapter: mysql2 encoding: utf8 reconnect: false database: Beispiel_development pool: 5 username: till password: geheim host: localhost socket: /var/mysql/mysql.sock Stimmt die Datenbank-Konfiguration, können die Datenbanken angelegt werden: noname:Beispiel till$ rake db:create (in /Users/till/rs/Beispiel) noname:Beispiel till$ Schaut man in mysql nach, findet man die angelegten Datenbanken: noname:Beispiel till$ mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 34 Server version: 5.5.0-m2 MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +----------------------+ | Database | +----------------------+ | information_schema | | Beispiel_development | | Beispiel_test | | mysql | +----------------------+ 10 rows in set (0.38 sec) mysql> rake erzeugt hier zwei Datenbanken, Beispiel_development und Beispiel_test. Diese beiden werden für die Entwicklung einer Anwendung benötigt. Die Produktionsumgebung (üblicherweise Beispiel_production) würde angelegt, wenn bei der rake task der Parameter RAILS_ENV=production mitgegeben würde. Objekte mit scaffolding erzeugenBeginnen wir mit der Entwicklung unserer Anwendung. Wir wollen ein einfaches Social Network entwickeln, eine Online Kontaktbörse. Das Analysis-Level Datenmodell soll so aussehen:
Beginnen wir mit der Tabelle Person. Zunächst müssen wir die entsprechende Tabelle in der Datenbank anlegen und den Code zum Zugriff darauf (Personen anlegen, ändern, suchen usw.) erzeugen. Im ersten Schritt lassen wir dies von rails automatisch erledigen. Später werden wir sehen, wie diese einzelnen Schritte manuell ausgeführt werden köhrt werden können. Zunächst müssen wir festlegen, welche Typen die Attribute einer Person haben sollen. In unserem Fall sind das bis auf die PLZ alles Strings. Die PLZ stellen wir als integer Zahl dar. noname:Beispiel till$ rails generate scaffold Person Nickname:string Name:string Vorname:string email:string Geburtsdatum:string PLZ:integer Geschlecht:string Ich:string IchKurz:string invoke active_record create db/migrate/20110124135102_create_people.rb create app/models/person.rb invoke test_unit create test/unit/person_test.rb create test/fixtures/people.yml route resources :people invoke scaffold_controller create app/controllers/people_controller.rb invoke erb create app/views/people create app/views/people/index.html.erb create app/views/people/edit.html.erb create app/views/people/show.html.erb create app/views/people/new.html.erb create app/views/people/_form.html.erb invoke test_unit create test/functional/people_controller_test.rb invoke helper create app/helpers/people_helper.rb invoke test_unit create test/unit/helpers/people_helper_test.rb invoke stylesheets create public/stylesheets/scaffold.css noname:Beispiel till$ Wie man sieht, werden eine Menge Dateien erzeugt, insbesondere eine Migration, ein Model (app/models/person.rb), ein Controller (app/views/people_controller.rb) und eine Reihe von Views (app/views/people/*). Die Migration enthält die notwendigen Informationen, um die Datenbank auf den aktuellen Stand zu bringen. In unserem Fall also von nichts zur Tabelle Person.
Diese Migration kann mit dem Befehl rake db:migrate ausgeführt werden. Dabei wird dann die Tabelle Person angelegt. noname:Beispiel till$ rake db:migrate (in /Users/till/rs/Beispiel) == CreatePeople: migrating =================================================== -- create_table(:people) -> 0.1897s == CreatePeople: migrated (0.1898s) ========================================== noname:Beispiel till$ noname:Beispiel till$ noname:Beispiel till$ mysql -u root mysql> use Beispiel_development; mysql> show tables; +--------------------------------+ | Tables_in_beispiel_development | +--------------------------------+ | people | | schema_migrations | +--------------------------------+ 2 rows in set (0.00 sec) mysql> describe people; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | Nickname | varchar(255) | YES | | NULL | | | Name | varchar(255) | YES | | NULL | | | Vorname | varchar(255) | YES | | NULL | | | email | varchar(255) | YES | | NULL | | | Geburtsdatum | varchar(255) | YES | | NULL | | | PLZ | int(11) | YES | | NULL | | | Geschlecht | varchar(255) | YES | | NULL | | | Ich | varchar(255) | YES | | NULL | | | IchKurz | varchar(255) | YES | | NULL | | | created_at | datetime | YES | | NULL | | | updated_at | datetime | YES | | NULL | | +--------------+--------------+------+-----+---------+----------------+ 12 rows in set (0.00 sec) mysql> Mit dem mysql-Client lässt sich der Erfolg dieser Operation betrachten: Die Tabelle people in der Datenbank Beispiel_development wurde erzeugt. Sie enthält die Attribute, die bei der Erzeugung des scaffolds (genauer des models) angegeben wurden. Zusätzlich findet man noch einige von rails automatisch erzeugte Attribute: id, der Primärschlüssel identifiert eine Person und wird automatisch verwaltet. Die Attribute created_at und updated_at werden von rails ebenfalls automatisch angelegt und verwaltet. Dort wird Buch darüber geführt, wann Datensätze erzeugt und geändert wurden. Mit dieser erzeugten Anwendung kann bereits gearbeitet werden, sie enthält im Prinzip alles, was benötigt wird, um Personen zu verwalten. Unter der URL http://localhost:3000/people kann eine Liste der existierenden Personen aufgerufen werden bzw. neue Personen angelegt, bearbeitet und gelöscht werden, nachdem der Server wieder mit rails server gestartet wurde.
Eine zweite Tabelle dazu ... MessagesEine Anwendung besteht im Allgemeinen aus mehr als einer Klasse/Tabelle. So auch hier. Wir machen also mit einer zweiten Tabelle weiter, mit den Messages. Unsere Benutzer sollen Nachrichten austauschen können, diese werden in der Tabelle Messages gespeichert. Eine Nachricht gehört immer einer Person, dem Empfänger. Wir erzeugen wieder mit dem scaffold-Mechanismus das Model, den Controller und die Views und legen mit rake db:migrate die Tabelle messages an. noname:Beispiel till$ rails generate scaffold Message Absender:string Betreff:string Text:string Datum:datetime person:references invoke active_record create db/migrate/20110124142849_create_messages.rb create app/models/message.rb invoke test_unit create test/unit/message_test.rb create test/fixtures/messages.yml route resources :messages invoke scaffold_controller create app/controllers/messages_controller.rb invoke erb create app/views/messages create app/views/messages/index.html.erb create app/views/messages/edit.html.erb create app/views/messages/show.html.erb create app/views/messages/new.html.erb create app/views/messages/_form.html.erb invoke test_unit create test/functional/messages_controller_test.rb invoke helper create app/helpers/messages_helper.rb invoke test_unit create test/unit/helpers/messages_helper_test.rb invoke stylesheets identical public/stylesheets/scaffold.css noname:Beispiel till$ noname:Beispiel till$ rake db:migrate (in /Users/till/rs/Beispiel) == CreateMessages: migrating ================================================= -- create_table(:messages) -> 0.2027s == CreateMessages: migrated (0.2029s) ======================================== Wiederum können wir uns davon überzeugen, dass wir eine funktionierende Anwendung haben, indem wir die URL http://localhost:3000/messages aufrufen. Aber so können wir natürlich nichts mit den Messages anfangen, eine Nachricht gehört ja zu einem Benutzer (wir wollen ja nicht alle Nachrichten sehen, sondern nur die eines Benutzers). Dass eine Nachricht zu einer Person gehört, haben wir bereits festgelegt. Die Angabe des Pseudo-Attributs person mit dem Typ references drückt die "N-Seite" einer 1:N Beziehnung aus. Die andere Seite (bei der Person) müssen wir noch definieren. Dazu erweitern wir das Model Person um eine Assoziation:
Eine entsprechende Ergänzung im Model der Klasse Message hat rails beim scaffolding automatisch erzeugt, dort als belongs_to :person. Im Model haben wir jetzt die Beziehung zwischen Personen und Messages hergestellt, in der Anwendung (natürlich) noch nicht. Ein Benutzer muss seine Nachrichten lesen und neue verfassen können. Da diese Funktionalität aber im Allgemeinen anwendungsspezifisch ist, könnten wir hier mit automatisch generiertem Code sowieso nicht viel anfangen. rails erzeugt aus diesem Grund auch keinen solchen Code. Das beudeutet aber nicht, das rails uns hier nicht die Arbeit (erheblich) erleichtert, bereits der Model-Code stellt eine ganze Menge Funktionalität zur Verfügung. Ein Person-Objekt hat jetzt beispielsweise eine Enumeration messages, die alle Nachrichten dieser Perosn enthät. Die Verbindung zwischen den Personen und ihren NachrichtenZu jeder Person soll jetzt angezeigt werden, wieviele Nachrichten im Posteingang sind. Dazu müssen wir zunächst in der Datenbank nachschauen, wieviele Nachrichten zur aktuellen Person vorhanden sind und diese Zahl dann ausgeben. Nachgeschaut wird im Controller (people_controller.rb). Die Methode messages des Person-Objekts wurde von rails automatisch erzeugt, durch sie erhalten wir Zugriff auf alle Nachrichten dieser Person. def show @person = Person.find(params[:id]) @Nachrichten = @person.messages Ausgegeben wird im view (show.html.erb im Unterverzeichnis views/people). <%=@Nachrichten.count> Nachrichten |