Active Record, ActiveRelation, Models
Active Record vs ActiveRecord vs ActiveRelation
a design pattern for relational databases
is cross plattform (implemented in different language)
let's you work with data as objects, not just static rows
simplifies database operations, including select, insert, updates, delete
a Ruby library that let's implements principles of Active Record as pattern.
Simplifies the generation of complex SQL queries
used by ActiveRecord for queries and management of relationship
user = User.new user.first_name = "Mark" user.save # SQL INSERT user.last_name = "Twain" user.save # SQL UPDATE user.delete #SQL DELETE
users = User.where(:first_name => "Mark") users = users.order("last_name ASC").limit(3) users = users.include(:books_written)
allows you to interact with your model the way irb let's you interact with Ruby interpreter. $rails console || rails c
loads rails environment into irb
E.g.: from rails console: Subject.new will create a subject object with attributes mimicking table fields.
CREATE / UPDATE / DELETE / FIND Records
Two ways to create new records.
all three steps as a single command
# Number 1 (new / save) subject = Subject.new #creates a new record object (not yet committed to the database) subject.name = "Something"
Alternative way to write it is: subject = Subject.new(:name => "First Subject", :position => 1, :visible => true) subject.save #saves it to the database subject.new_record? #check if the record is still not committed to the database
# Number 2 (create) subject = Subject.create(:name => "Second Subject", :position => 2) # this will commit a record to db and create an object that reflects the newly created record
The first method is used more frequently, since it gives us the flexibility to change an object before committing it to the db.
# Number 1 (find / update / save) subject = Subject.find(1) subject.name = "Updated Name" #note that name is not updated in the db until `subject.save` is executed subject.save # Number 2 (find / update_attr) subject = Subject.find(2) subject.update_attributes(:name => "Revised Subject", :visible => true) #returns true/false based on if the update succeeded or not
find: subject = Subject.find(2) #by ID in the subjects table
The object is accessible after the destroy operation, so the info in it can be used for different purposes (e.g. reporting)
bypasses some built-in mechanisms
faster, but doesn't leave a copy to work with
Returns an object or an error
find_by_[database field]: User.find_by_first_name("Tyson")
Returns an object or a nil
Returns an array of objects
Note: all the methods above make a call to the db Immediately
ActiveRelation (Query Methods)
Note: you can use .to_sql method on the AcriveRelation object to output the SQL that was generated.
Note: the where method returns an array, empty array, if no records were matched.
Note: .scoped method is used to instantiate an empty ActiveRelation object and with no additional constrains will match all records in the database. E.g.: User.scoped
Conditions (what conditions data has to meet in order to satisfy the request)
Old Query Methods (depricated in Rails 3.1 and removed in Rails 3.2)
User.find(:first_name, :conditions => ["first_name = ? AND email = '[email protected]'", "Ali"]
User.find(:all, :conditions => {:first_name => 'Bob'})
New (ActiveRelation) Query Methods
Returns an ActiveRelation object, which can be chained
Name.where(:first_name => 'Ali').order("email ASC")
does not execute a database call immediately
condition can be of three different types:
String "first_name = 'Ali' AND last_name = 'Muhammad'
susceptible to SQL injections
Array ["first_name = ? AND last_name = 'Muhammad']
Hash {:first_name => "Ali", :last_name => "Muhammad"}
Only supports equality, range and subject checking
User.find(:all, :order => "email ASC", :limit => 20, :offset => 40)
offset(integer) #skip over a certain number of records
E.g.: 1) order: user.order("[user.]email ASC, [user.]last_name DESC") 2) limit: user.limit(1) 3) offset: user.offset(1).limit(1)
Let's you store queries in the model.
You call them same as regular ActiveRecord methods
Note: prior Rails 3.0 the method was called named_scope, now it is simply called scope.
in a model class do the following:
scope :klichko where({:first_name => 'Klichko'}) #where ":klichko" is a named scope name
scope :search, lambda {|query| where(["name LIKE ?", "%#{query}%"])}