ActiveRecord ist einer der Gründe, wieso Ruby on Rails so einfach und flexibel ist. Es ist ein sogenannter objektrelationaler Mapper. Damit lassen sich Daten aus einer Datenbank wie Objekte behandeln. Aber auch ohne Rails läßt sich ActiveRecord recht einfach einsetzen.
Als Beispiel habe ich hier 2 Tabellen in PostgreSQL, in denen ich eine Auswahl an Artikeln speichern möchte. Die Tabelle selections
enthält den Namen der Auswahl von Artikeln und in selectionitems
befinden sich die Artikel aus Auswahllisten. Die Tabellen haben folgendes Schema:
CREATE TABLE selections ( id SERIAL PRIMARY KEY, name VARCHAR(30) ); CREATE TABLE selectionitems ( id SERIAL PRIMARY KEY, part_id INTEGER, selection_id INTEGER, sort_order INTEGER );
Die beiden Tabellen habe ich mit Testdaten gefüllt.
artikel=# select * from selections; id | name ----+------ 1 | foo (1 row) artikel=# select * from selectionitems; id | part_id | selection_id | sort_order ----+---------+--------------+------------ 1 | 23 | 1 | 3 2 | 42 | 1 | 1 3 | 123 | 1 | 2 (3 rows)
Die Namen der Tabellen und der Felder sind schon ziemlich Rails-like, so daß in den folgenden Beispielen sehr viele Einstellungen überflüssig sind. Aber ich habe sie hier eingetragen, um zu zeigen, wie man mit beliebigen Tabellen arbeiten könnte.
Mit ActiveRecord verpacke ich nun die beiden Tabellen. Falls es beim require
bzw. require_gem
zu Fehlern kommen sollte, sind vermutlich die Ruby Gems bzw. das ActiveRecord-Gem nicht installiert. (Genaueres ist auf der Ruby Gems Website beschrieben)
require 'rubygems' require_gem 'activerecord' ActiveRecord::Base.establish_connection( :adapter => "postgresql", :host => "localhost", :database => "artikel", :username => "dbuser", :password => "kryptisches_passwort" ) class Selection < ActiveRecord::Base set_table_name "selections" set_primary_key "id" has_many :items, :class_name => "SelectionItem", :foreign_key => "selection_id", :order => "sort_order" end class SelectionItem < ActiveRecord::Base set_table_name "selectionitems" set_primary_key "id" belongs_to :selection, :class_name => "Selection", :foreign_key => "selection_id" end
Das war der ganze Code, um die beiden Tabellen in Objekte zu verpacken. Was genau steht nun da oben? ActiveRecord::Base.establish_connection()
dürfte eigentlich selbsterklärend sein. Interessant wird es bei der Klasse Selections
. Ich sage der Klasse mit set_table_name
auf welcher Tabelle aus der Datenbank sie basieren soll und mit set_primary_key
wie die Spalte mit dem Primärschlüssel heißt. (ActiveRecord hat hier einige Automatismen um vom Namen der Klasse auf den Tabellennamen zu schließen, die ich jedoch bewußt nicht benutzt habe.) Mit has_many
habe ich bestimmt, daß jede Instanz der Klasse Selections
mehrere Instanzen der Klasse SelectionItem
enthalten kann. Die Zuordnung dieser items
zu einer Selection
geschieht anhand der selection_id
aus SelectionItem
. Ähnlich habe ich auch in SelectionItem
bestimmt, auf welcher Tabelle es basieren soll. Und umgekehrt zu has_many
habe ich hier mit belongs_to
festgelegt, daß eine Instanz von SelectionItem
zu einer bestimmten Selection
gehört.
Wie benutze ich das nun? Ich ich suche erstmal die in den Tabellen gespeicherte Auswahl.
irb(main):028:0> foo = Selection.find_by_name("foo") => #"foo", "id"=>"1"}>
Wer Ruby on Rails schon gesehen hat, wird das wiedererkennen. Und all die anderen halten es für Magie :) Hier ist die erste Auswahl mit den Namen foo
. Diese Auswahl enthält nun einige Artikel. Mal schauen, was ich da habe.
irb(main):029:0> foo.items.count => 3 irb(main):030:0> foo.items.each { |bar| puts bar.part_id } 42 123 23
Da ist meine Auswahl. Jetzt will ich ein weiteren Artikel zu dieser Auswahl hinzufügen.
irb(main):031:0> foo.items.create(:part_id => 451, :sort_order => 4) => #>, @attributes={"part_id"=>451, "sort_order"=>4, "selection_id"=>1, "id"=>4}> irb(main):032:0> foo.items.count => 4 irb(main):033:0> foo.items.each { |bar| puts bar.part_id } 42 123 23 451
Das war aber noch nicht alles. Ich möchte in meiner Auswahl den zweiten Artikel herausfinden.
irb(main):035:0> foo.items.find_by_sort_order(2).part_id => 123
Ich kann diese Auswahl aber auch wie ein Array betrachten. (Achtung, Arrays fangen bei 0 an!)
irb(main):038:0> foo.items[1].part_id => 123
Besondere Erwähnung verdient die Suchfunktion. Ich sage nur find_by_feldname
, und es wird anhand dieses Feldes in der Tabelle gesucht. ActiveRecord erzeugt also automagisch für alle Tabellenfelder find-Methoden. Das geht sogar so weit, daß man auch mehrere Suchkriterien kombinieren kann.
irb(main):041:0> foo.items.find_by_part_id_and_sort_order(123,2) => #"123", "sort_order"=>"2", "selection_id"=>"1", "id"=>"3"}>
Wenn ActiveRecord nichts findet, gibt es einfach nil
zurück.
irb(main):040:0> foo.items.find_by_part_id_and_sort_order(123,3) => nil
Und für all diejenigen, die ihren Augen noch nicht trauen, hier noch ein letzter Blick in die Datenbank. Ich zeige hier nur die Tabelle selectionitems
, da ich nur darin was geändert habe.
artikel=# select * from selectionitems; id | part_id | selection_id | sort_order ----+---------+--------------+------------ 1 | 23 | 1 | 3 2 | 42 | 1 | 1 3 | 123 | 1 | 2 4 | 451 | 1 | 4 (4 rows)
Wer sich nun mit den Details von ActiveRecord auseinander setzen möchte, sollte in die Ruby on Rails-Dokumentation schauen.