4.3. Adding Records

Actually, I would like to show you first how to view records, but there we have another chicken and egg problem. So first, here is how you can create a new record with ActiveRecord.

create

The most frequently used method for creating a new record is create. As usual, there is a separate help page on this topic available in the system:
$ ri -T ActiveRecord::Persistence::ClassMethods#create
ActiveRecord::Persistence::ClassMethods#create

(from gem activerecord-3.2.9)
------------------------------------------------------------------------------
  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


$
Wonderful, it even gives you examples! What more could we want? Let's try creating a country in the console using this method:
$ rails console
Loading development environment (Rails 3.2.9)
>> Country.create(:name => 'Germany', :population => 81831000)
   (0.1ms)  begin transaction
  SQL (29.6ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Wed, 14 Nov 2012 11:14:55 UTC +00:00], ["name", "Germany"], ["population", 81831000], ["updated_at", Wed, 14 Nov 2012 11:14:55 UTC +00:00]]
   (0.9ms)  commit transaction
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> exit
$
ActiveRecord saves the new record and outputs the executed SQL command in the development environment. But to make absolutely sure it works, let's have a quick look with the command line client sqlite3:
$ sqlite3 db/development.sqlite3 
SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> SELECT * FROM countries;
1|Germany|81831000|2012-11-14 11:14:55.281497|2012-11-14 11:14:55.281497
sqlite> .exit
$

Syntax

The method create can handle a number of different syntax constructs. If you want to create a single record, you can do this with or without {}-brackets within the the ()-brackets:
  • Country.create(:name => 'Germany', :population => 81831000)
  • Country.create( {:name => 'Germany', :population => 81831000} )
Similarly, you can describe the attributes differently:
  • Country.create(:name => 'Germany', :population => 81831000)
  • Country.create('name' => 'Germany', 'population' => 81831000)
  • Country.create( name: 'Germany', population: 81831000 )
You can also pass an array of hashes to create and use this approach to create several records at once:
Country.create( [ {:name => 'Germany', :population => 81831000}, {"name"=>"France", "population"=>65447374} ] )

new

In addition to create there is also new. But you have to use save to save an object created with new (which has both advantages and disadvantages):
$ rails console
Loading development environment (Rails 3.2.9)
>> france = Country.new
=> #<Country id: nil, name: nil, population: nil, created_at: nil, updated_at: nil>
>> france.name = 'France'
=> "France"
>> france.population = 65447374
=> 65447374
>> france.save
   (0.2ms)  begin transaction
  SQL (25.3ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Wed, 14 Nov 2012 11:16:49 UTC +00:00], ["name", "France"], ["population", 65447374], ["updated_at", Wed, 14 Nov 2012 11:16:49 UTC +00:00]]
   (2.4ms)  commit transaction
=> true
>> france
=> #<Country id: 2, name: "France", population: 65447374, created_at: "2012-11-14 11:16:49", updated_at: "2012-11-14 11:16:49">
>> 
You can also pass parameters for the new record directly to the method new, just as with create:
>> belgium = Country.new(:name => 'Belgium', :population => 10839905)
=> #<Country id: nil, name: "Belgium", population: 10839905, created_at: nil, updated_at: nil>
>> belgium.save
   (0.2ms)  begin transaction
  SQL (28.6ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Wed, 14 Nov 2012 11:18:21 UTC +00:00], ["name", "Belgium"], ["population", 10839905], ["updated_at", Wed, 14 Nov 2012 11:18:21 UTC +00:00]]
   (2.4ms)  commit transaction
=> true
>> exit
$

new_record?

With the method new_record? you can find out if a record has already been saved or not. If a new object has been created with new and not yet been saved, then the result of new_record? is true. After a save it is false.
Example:
$ rails console
Loading development environment (Rails 3.2.9)
>> netherlands = Country.new(:name => 'Netherlands', :population => 16680000)
=> #<Country id: nil, name: "Netherlands", population: 16680000, created_at: nil, updated_at: nil>
>> netherlands.new_record?
=> true
>> netherlands.save
   (0.2ms)  begin transaction
  SQL (5.9ms)  INSERT INTO "countries" ("created_at", "name", "population", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Wed, 14 Nov 2012 11:19:51 UTC +00:00], ["name", "Netherlands"], ["population", 16680000], ["updated_at", Wed, 14 Nov 2012 11:19:51 UTC +00:00]]
   (2.3ms)  commit transaction
=> true
>> netherlands.new_record?
=> false
>> exit
$

Tip

For already existing records, you can also check for changes with the method changed? (see the section called “changed?”).

Updates about this book will be published on my Twitter feed.