Neu: Das englische Ruby on Rails 4.0 Buch.

4.3. Datensätze hinzufügen

Eigentlich würde ich Ihnen ja gerne erst zeigen, wie man sich Datensätze anzeigen lassen kann, aber da haben wir natürlich ein Henne-Ei-Problem. Deshalb jetzt erst mal das Anlegen von neuen Datensätzen mit ActiveRecord.

create

Die am häufigsten zum Anlegen von neuen Datensätzen benutzte Methode ist create. Wie immer gibt es dazu eine eigene Hilfeseite im System:
MacBook:europe xyz$ ri -T ActiveRecord::Persistence::ClassMethods#create
ActiveRecord::Persistence::ClassMethods#create

(from gem activerecord-3.2.8)
------------------------------------------------------------------------------
  create(attributes = nil, options = {}, &block)

------------------------------------------------------------------------------

Creates an object (or multiple objects) and saves it to the database, if
validations pass. The resulting object is returned whether the object was
saved successfully to the database or not.

The attributes parameter can be either be a Hash or an Array of Hashes.
These Hashes describe the attributes on the objects that are to be created.

create respects mass-assignment security and accepts either :as
or :without_protection options in the options parameter.

Examples
  # Create a single new object
  User.create(:first_name => 'Jamie')

  # Create a single new object using the :admin mass-assignment security role
  User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)

  # Create a single new object bypassing mass-assignment security
  User.create({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)

  # Create an Array of new objects
  User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])

  # Create a single object and pass it into a block to set other attributes.
  User.create(:first_name => 'Jamie') do |u|
    u.is_admin = false
  end

  # Creating an Array of new objects using a block, where the block is executed for each object:
  User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
    u.is_admin = false
  end



MacBook:europe xyz$
Super, direkt mit Beispielen! Was will man mehr? Versuchen wir mal so in der Console ein Land anzulegen:
MacBook:europe xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > Country
 => Country(id: integer, name: string, population: integer, created_at: datetime, updated_at: datetime) 
1.9.3p194 :002 > Country.create(:name => 'Deutschland', :population => 81831000) 
   (0.1ms)  begin transaction
  SQL (39.9ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 26 Apr 2012 10:26:38 UTC +00:00], ["name", "Deutschland"], ["population", 81831000], ["updated_at", Thu, 26 Apr 2012 10:26:38 UTC +00:00]]
   (1.5ms)  commit transaction
 => #<Country id: 1, name: "Deutschland", population: 81831000, created_at: "2012-04-26 10:26:38", updated_at: "2012-04-26 10:26:38"> 
1.9.3p194 :003 > exit
MacBook:europe xyz$
ActiveRecord speichert den neuen Datensatz und gibt uns in der Development-Umgebung auch den ausgeführten SQL-Befehl aus. Um aber ganz sicher zu gehen, schauen wir kurz mit dem Kommandozeilen-Client sqlite3 nach:
MacBook:europe xyz$ sqlite3 db/development.sqlite3 
SQLite version 3.7.7 2011-06-25 16:35:41
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> SELECT * FROM countries;
1|Deutschland|81831000|2012-04-26 10:26:38.533290|2012-04-26 10:26:38.533290
sqlite> .exit
MacBook:europe xyz$

Syntax

Die create-Methode verdaut eine Reihe von unterschiedlichen Syntax-Konstrukten. Wenn Sie einen einzelnen Datensatz anlegen wollen, so können Sie dies mit und ohne {}-Klammern innerhalb der ()-Klammern machen:
  • Country.create(:name => 'Deutschland', :population => 81831000)
  • Country.create( {:name => 'Deutschland', :population => 81831000} )
Ebenfalls können die Attributes unterschiedlich beschrieben werden:
  • Country.create(:name => 'Deutschland', :population => 81831000)
  • Country.create('name' => 'Deutschland', 'population' => 81831000)
  • Country.create( name: 'Deutschland', population: 81831000 )
Sie können auch einen Array von Hashes an create übergeben und damit mehrere Datensätze auf einmal erstellen:
Country.create( [ {:name => 'Deutschland', :population => 81831000}, {"name"=>"Frankreich", "population"=>65447374} ] )

new

Neben create gibt es auch new. Allerdings muss ein mit new erzeugtes Objekt extra mit save gespeichert werden (was Vor- und Nachteile hat):
MacBook:europe xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > frankreich = Country.new
 => #<Country id: nil, name: nil, population: nil, created_at: nil, updated_at: nil> 
1.9.3p194 :002 > frankreich.name = 'Frankreich'
 => "Frankreich" 
1.9.3p194 :003 > frankreich.population = 65447374
 => 65447374 
1.9.3p194 :004 > frankreich.save
   (0.1ms)  begin transaction
  SQL (5.6ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 26 Apr 2012 10:41:54 UTC +00:00], ["name", "Frankreich"], ["population", 65447374], ["updated_at", Thu, 26 Apr 2012 10:41:54 UTC +00:00]]
   (4.5ms)  commit transaction
 => true 
1.9.3p194 :005 > frankreich
 => #<Country id: 2, name: "Frankreich", population: 65447374, created_at: "2012-04-26 10:41:54", updated_at: "2012-04-26 10:41:54"> 
1.9.3p194 :006 > exit
MacBook:europe xyz$
Sie können der Methode new wie create auch direkt Parameter für den neuen Datensatz übergeben:
MacBook:europe xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > belgien = Country.new(:name => 'Belgien', :population => 10839905)
 => #<Country id: nil, name: "Belgien", population: 10839905, created_at: nil, updated_at: nil> 
1.9.3p194 :002 > belgien.save
   (0.2ms)  begin transaction
  SQL (34.8ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 26 Apr 2012 10:44:49 UTC +00:00], ["name", "Belgien"], ["population", 10839905], ["updated_at", Thu, 26 Apr 2012 10:44:49 UTC +00:00]]
   (2.5ms)  commit transaction
 => true 
1.9.3p194 :003 > exit
MacBook:europe xyz$ 

new_record?

Mit der Methode new_record? können Sie sich anzeigen lassen, ob ein Datensatz bereits gespeichert wurde oder nicht. Wurde ein neues Objekt mit new erstellt und noch nicht abgespeichert, dann ist das Ergebnis von new_record? true. Nach einem save ist es false.
Beispiel:
MacBook:europe xyz$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > niederlande = Country.new(:name => 'Niederlande', :population => 16680000)
 => #<Country id: nil, name: "Niederlande", population: 16680000, created_at: nil, updated_at: nil> 
1.9.3p194 :002 > niederlande.new_record?
 => true 
1.9.3p194 :003 > niederlande.save
   (0.2ms)  begin transaction
  SQL (34.9ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 26 Apr 2012 10:47:23 UTC +00:00], ["name", "Niederlande"], ["population", 16680000], ["updated_at", Thu, 26 Apr 2012 10:47:23 UTC +00:00]]
   (3.8ms)  commit transaction
 => true 
1.9.3p194 :004 > niederlande.new_record?
 => false 
1.9.3p194 :005 > exit
MacBook:europe xyz$

Tipp

Bei bereits bestehenden Datensätzen können Sie eine Veränderung auch mit der Methode changed? überprüfen (siehe „changed?“).