Insert
New model objects are created using a object = Class.new ... object.save paradigm.
The following methods are supported:
Explicit:
object = class.new
object.attribute = value
...
object.save
Block:
Class.new do |obj|
obj.attribute = value
...
obj.save
end
Hash:
obj = Class.new (
:attribute => value
...
)
obj.save
Note: the new constructor creates a new Class object in memory - but the save
method must be called in order to save it to the database.
.save returns true if successful, nil if not.
.save! returns true if successful but raises an exception if not.
Use of the AR create method will both instantiate the model object _and_ store
it in the database. This method can only be used with a hash of attributes or
an array of attribute hashes:
obj = Class.create( :attribute => value, ... )
objs = Class.create
([
{ :attribute => value, ... },
...
{ :attribute => value, ... }
])
Note:
.create returns an AR object regardless of successful saving. The returned object
will need to be checked for validation errors in order to determine if data was
saved or not.
.create! returns an AR object if successful, but raises an exception if not.
Update
Given an AR object, calling it's save method will either create a new record
or update an existing one.
AR will use the PK column (id) to match itself with a table row. The attributes
in the AR object determine which columns will be updated, and such columns will
only be updated if their value has changed.
Hence in,
ord = Order.find(12)
ord.name = "Foo"
ord.save
All columns in the row for Order 12 can be updated (although only :name
in this example).
Whilst in,
ords = Order.find_by_sql("select id, name, pay_type from orders where id = 12")
first = ords[0]
first.name = Bar"
first.pay_type = "po"
first.save
only the :name and :pay_type columns will update in the associated row.
Other update methods -
(1) update_attribute(): update an attribute or a hash of attributes in a single call:
ord = Order.find(12)
ord.update_attribute(:name, "Foo")
ord = Order.find(12)
ord.update_attributes(:name => "Foo", pay_type => "po")
(2) update/update_all:
The update method takes an id parameter and a set of attributes. It fetches the
corresponding row, updates the attributes, saves the result to the database, and
returns the model object.
Note: an array of ids and an array of attribute hashes may also be sent to this method
resulting in the update of multiple rows, which are then returned.
Update_all('set clause', 'where clause') method allows one to specify the set
and where clauses of the SQL update statement. What this method returns is
adapter specific - but it is most commonly the number of rows changed.
Delete
Only 2 styles of delete are supported:
(1) delete / delete_all (Class level)
Explicit or Hash -
delete(:id) or delete([:id])
A given condition (where clause) -
Order.delete_all(["fillDate <= ?", @some_ancient_date])
(2) destroy / destroy_all (instance/class level)
instance level:
ord = Order.find_by_name("Foo");
ord.destroy
This method deletes the row from the database which corresponds to the
model object and then freezes the contents of that object, preventing further
changes to the attributes.
class level:
destroy takes an id or arrays of ids, destroy_all takes a condition (as with delete
above).
Both read the corresponding rows in the database tables into model objects and
call the instance level destroy method of each object. Neither method returns
anything meaningful.
What is the difference between delete and destroy?
The delete methods bypass the various AR callback and validation functions, while
destroy methods ensure that they are all invoked.
It is, in general, better to use the destroy methods if one wishes to ensure that
ones database is consistent according to the business rules define in ones model
classes.
Few things about Primary Keys and Ids
Rails manages the creation of primary keys for new schemas: all tables have an id primary
key column added to them. Note, that AR does provide a simple means of overriding this default
by using the following construct:
class LegacyBook < ActiveRecord::Base
self.primary_key = "your PK Name"
end
Warning: As far as AR is concerned, the PK attribute is always set using an attribute called id.
The .primary_key = declaration sets the name of the column to use in the table. In the following code, we
use an attribute id even though the PK in the DB is "your PK Name":
book = LegacyBook.New
book.id = "3225453453"
book.title = "Blah"
book.save
book = LegacyBook.find("3225453453")
puts book.title # => "Blah"
puts book.attributes #=> { "your PK Name" => "3225453453", "title" => "Blah" }
Just to make things more confusing, the attributes of the model object have the names "your PK Name",
"title" - id does not appear. When you need to set the PK, use id. At all other times
use the actual column name.
Note: Rails does NOT support composite PKs.