SlideShare una empresa de Scribd logo
1 de 72
Descargar para leer sin conexión
Introduction to
 Active Record
    Evan ‘Rabble’ Henshaw-Plath
evan@protest.net - Yahoo! Brickhouse
 anarchogeek.com - testingrails.com
Active Record is a
    Design Pattern
An object that wraps a row in a database table
or view, encapsulates the database access, and
        adds domain logic on that data.
Active Record
          the Pattern
                 Person
            last_name
            first_name
            dependents_count
            insert
            update

            get_exemption
            is_flagged_for_audit?
            get_taxable_earnings?




Active Record uses the most obvious approach,
 putting data access logic in the domain object.
                - Martin Fowler
One Class Per Table
The Model Code                    The Database
class User < ActiveRecord::Base   CREATE TABLE `users` (
                                    `id` int(11) NOT NULL auto_increment,
end
                                    `login` varchar(255),
                                    `email` varchar(255),
                                    `crypted_password` varchar(40),
                                    `salt` varchar(40),
                                    `created_at` datetime default NULL,
                                    `updated_at` datetime default NULL,
                                    PRIMARY KEY (`id`)
                                  ) ENGINE=InnoDB;
One Object Per Row
There Are Other Ways
      To Do it
Active Record is
just one ‘Data Source
Architectural Pattern’

• Table Data Gateway
• Row Data Gateway
• Data Mapper
• The Anti-Patterns
Standard Active Record

• Direct mapping to the DB
 • Class to table
 • Object to row
• Simple, no relationship between objects
• Just a finder method with getters and setters
ActiveRecord
       the ruby library
Active Record is
a library built
for Ruby on Rails.

Makes CRUD Easy
Create
Read
Update
Delete
ActiveRecord
     the ruby library
I have never seen an Active Record
    implementation as complete
or as useful as rails. - Martin Fowler
Rails’ ActiveRecord
• DRY Conventions & Assumptions
• Validations
• Before and after filters
• Database Agnostic (mostly)
• Migrations
• Model relationships
 • has_many, belongs_to, etc...
What Active
Record Likes
• mapping class names to
  table names
• pluralized table names
• integer primary keys
• classname_id foreign keys
• simple schemas
• single table inheritance
Active Record
 Doesn’t Like
 • views
 • stored procedures
 • foreign key constraints
 • cascading commits
 • split or clustered db’s
 • enums
The Basics
./app/models/user.rb                Loading a user
class User < ActiveRecord::Base
                                    >> user_obj = User.find(2)
end
                                    => #<User:0x352e8bc
                                    @attributes=
                                     {"salt"=>"d9ef...",
The SQL Log                           "updated_at"=>"2007-04-19 10:49:15",
                                      "crypted_password"=>"9c1...",
User Load (0.003175)                  "id"=>"2",
	    SELECT * FROM users              "remember_token"=>"a8d...",
	    WHERE (users.id = 2) LIMIT 1     "login"=>"rabble",
                                      "created_at"=>"2007-04-19 10:49:15",
                                      "email"=>"evan@protest.net"}>
The Find Method
Find is the primary method of Active Record

Examples:
	   User.find(23)
	   User.find(:first)
	   User.find(:all, :offset => 10, :limit => 10)
	   User.find(:all, :include => [:account, :friends])
	   User.find(:all, :conditions =>

   
 [“category in (?), categories, :limit => 50)
	   User.find(:first).articles
The Four Ways of Find
Find by id: This can either be a specific id (1), a list of ids (1, 5,
6), or an array of ids ([5, 6, 10]).

Find first: This will return the first record matched by the
options used.

Find all: This will return all the records matched by the options
used.

Indirectly: The find method is used for AR lookups via
associations.
Understanding Find

Model#find(:all, { parameters hash }

What Find Does:
	 * generates sql
	 * executes sql
	 * returns an enumerable (array like object)
	 * creates an AR model object for each row
Find with :conditions
:conditions - An SQL fragment like
	 "administrator = 1" or [ "user_name = ?", username ].

Student.find(:all, :conditions =>

 [‘first_name = ? and status = ?’ ‘rabble’, 1])

New Style (Edge Rails Only)
Student.find(:all, :conditions => {:first_name => “rabble”, :status => 1})

SQL Executed:
SELECT * FROM students WHERE (first_name = 'rabble' and status = 1);
Order By

:order - An SQL fragment like "created_at DESC,
name".

Student.find(:all, :order => ‘updated_at DESC’)

SQL Executed:
SELECT * FROM users ORDER BY created_at;
Group By

:group - An attribute name by which the result
should be grouped. Uses the GROUP BY SQL-clause.

Student.find(:all, :group => ‘graduating_class’)

SQL Executed:
SELECT * FROM users GROUP BY graduating_class;
Limit & Offset
:limit - An integer determining the limit on the
number of rows that should be returned.

:offset- An integer determining the offset from
where the rows should be fetched. So at 5, it would
skip the first 4 rows.

Student.find(:all, :limit => 10, :offset => 0)

SQL Executed:
SELECT * FROM users LIMIT 0, 10;
Joins

:joins - An SQL fragment for additional joins like "LEFT JOIN
comments ON comments.post_id = id". (Rarely needed).

Student.find(:all, :join =>
	   "LEFT JOIN comments ON comments.post_id = id")

SQL Executed:
SELECT users.* FROM users, comments LEFT JOIN comments
ON comments.post_id = users.id;

Returns read only objects unless you say :readonly => false
Alternative Finds
find_by_sql
find_by_attribute_and_attribute2
find_or_create

Depreciated Find’s
find_first
find_all
find_on_conditions
Associations

The Four Primary Associations
belongs_to
has_one
has_many
has_and_belongs_to_many
class Project < ActiveRecord::Base
   belongs_to

 
 
 
 
 :portfolio
   has_one
 
 
 
 
 
 :project_manager
   has_many 
 
 
 
 
 
 :milestones
   has_and_belongs_to_many
 :categories
end
Associations

One to One
	 has_one & belongs_to
Many to One
	 has_many & belongs_to
Many to Many
	 has_and_belongs_to_many
	 has_many :through
One to One
Use has_one in the base, and belongs_to in the
associated model.

 class Employee < ActiveRecord::Base
  has_one :office
 end

 class Office < ActiveRecord::Base
  belongs_to :employee # foreign key - employee_id
 end
One To One Example
>> joe_employee = Employee.find_by_first_name('joe')
SELECT * FROM employees
	    WHERE (employees.`first_name` = 'joe') LIMIT 1
=> #<Employee:0x36beb14 @attributes={"id"=>"1", "first_name"=>"joe",
"last_name"=>"schmo", "created_at"=>"2007-04-21 09:08:59"}>

>> joes_office = joe_employee.office
SELECT * FROM offices WHERE (offices.employee_id = 1) LIMIT 1
=> #<Office:0x36bc06c @attributes={"employee_id"=>"1", "id"=>"1",
"created_at"=>"2007-04-21 09:11:44", "location"=>"A4302"}>

>> joes_office.employee
SELECT * FROM employees WHERE (employees.`id` = 1)
=> #<Employee:0x36b6ef0 @attributes={"id"=>"1", "first_name"=>"joe",
"last_name"=>"schmo", "created_at"=>"2007-04-21 09:08:59"}>
belongs_to
One to One Relationship.
Use belong to when the foreign key is in THIS table.

 •   Post#author (similar to Author.find(author_id) )
 •   Post#author=(author) (similar to post.author_id =
     author.id)
 •   Post#author? (similar to post.author == some_author)
 •   Post#author.nil?
 •   Post#build_author (similar to post.author =
     Author.new)
 •   Post#create_author (similar to post.author = Author;
     post.author.save;
Defining belongs_to
class Employee < ActiveRecord::Base
    belongs_to :firm, :foreign_key => "client_of"

    belongs_to :author, :class_name => "Person", :foreign_key => "author_id"

    belongs_to :valid_coupon, :class_name => "Coupon",


     
   :foreign_key => "coupon_id", :conditions => 'discounts > #{payments_count}'

    belongs_to :attachable, :polymorphic => true
end
has_one
One to One Relationship.
Use has_one when the foreign key is in the OTHER table.
 •   Account#beneficiary (similar to Beneficiary.find
     (:first, :conditions => "account_id = #{id}"))
 •   Account#beneficiary=(beneficiary) (similar to
     beneficiary.account_id = account.id; beneficiary.save)

 •   Account#beneficiary.nil?
 •   Account#build_beneficiary (similar to Beneficiary.new
     ("account_id" => id))

 •   Account#create_beneficiary (similar to b =
     Beneficiary.new("account_id" => id); b.save; b)
Defining has_one
class Employee < ActiveRecord::Base
 # destroys the associated credit card
 has_one :credit_card, :dependent => :destroy

 # updates the associated records foreign key value to null rather than destroying it
 has_one :credit_card, :dependent => :nullify

 has_one :last_comment, :class_name => "Comment", :order => "posted_on"

  has_one :project_manager, :class_name => "Person",
	    :conditions => "role = 'project_manager'"

 has_one :attachment, :as => :attachable

end
One to Many
One-to-many
Use has_many in the base, and belongs_to in
the associated model.

class Manager < ActiveRecord::Base
   has_many :employees
end

class Employee < ActiveRecord::Base
   belongs_to :manager # foreign key - manager_id
end
One to Many
>> benevolent_dictator = Manager.find(:first, :conditions => ['name = "DHH"'])
	 SELECT * FROM managers WHERE (name = "DHH") LIMIT 1
=> #<Manager:0x369b7b8 @attributes={"name"=>"DHH", "id"=>"1",
"created_at"=>"2007-04-21 09:59:24"}>

>> minions = benevolent_dictator.employees
	 SELECT * FROM employees WHERE (employees.manager_id = 1)
=> [#<Employee:0x36926a4 @attributes={"manager_id"=>"1", "id"=>"1",
"first_name"=>"joe", "last_name"=>"schmo", "created_at"=>"2007-04-21
09:08:59"}>,
	 #<Employee:0x36925f0 @attributes={"manager_id"=>"1", "id"=>"2",
"first_name"=>"funky", "last_name"=>"monkey", "created_at"=>"2007-04-21
09:58:20"}>]
has_many
                  Augmenting the Model
•   Firm#clients (similar to Clients.find :all, :conditions =>
    "firm_id = #{id}")
•   Firm#clients<<
•   Firm#clients.delete
•   Firm#client_ids
•   Firm#client_ids=
•   Firm#clients=
has_many
•   Firm#client.clear
•   Firm#clients.empty? (similar to firm.clients.size
    == 0)
•   Firm#clients.size (similar to Client.count
    "firm_id = #{id}")
•   Firm#clients.find (similar to Client.find(id, :conditions
    => "firm_id = #{id}"))
•   Firm#clients.build (similar to Client.new
    ("firm_id" => id))
•   Firm#clients.create (similar to c = Client.new
    ("firm_id" => id); c.save; c)
has_many examples
class Employee < ActiveRecord::Base
 has_many :comments, :order => "posted_on"
 has_many :comments, :include => :author
 has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
 has_many :tracks, :order => "position", :dependent => :destroy
 has_many :comments, :dependent => :nullify
 has_many :tags, :as => :taggable
 has_many :subscribers, :through => :subscriptions, :source => :user
 has_many :subscribers, :class_name => "Person", :finder_sql =>
   'SELECT DISTINCT people.* ' +
   'FROM people p, post_subscriptions ps ' +
   'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +
   'ORDER BY p.first_name'
end
Many to Many
    Simple Joiner Table
has_and_belongs_to_many

      Joiner Model
   has_many :through
has_and_belongs_to_many
  The Simple Joiner Table Way
has_and_belongs_to_many
neglected
    by
rails-core
has_and_belongs_to_many
                Augmenting the Model
  •   Developer#projects
  •   Developer#projects<<
  •   Developer#projects.delete
  •   Developer#projects=
  •   Developer#projects_ids
  •   Developer#projects_ids=
  •   Developer#clear
has_and_belongs_to_many

 •   Developer#projects.empty?
 •   Developer#projects.size
 •   Developer#projects.find(id) # Also find(:first / :all)
 •   Developer#projects.build #(similar to Project.new
     ("project_id" => id))
 •   Developer#projects.create (similar to c =
     Project.new("project_id" => id); c.save; c)
habtm example
create_table :developers do |t|
 t.column :name, :string
 t.column :created_at, :datetime
end

create_table :projects do |t|
 t.column :name, :string
 t.column :created_at, :datetime
end

create_table(:developers_projects, :id => false) do |t|
 t.column :developer_id, :integer
 t.column :project_id, :integer
end
habtm example
>> d = Developer.find(1)

    SELECT * FROM developers WHERE (developers.`id` = 1)
=> #<Developer:0x32bc7dc @attributes={"name"=>"rabble", "id"=>"1",
"created_at"=>nil}>

>> d.projects

     SELECT * FROM projects INNER JOIN developers_projects ON projects.id =
developers_projects.project_id WHERE (developers_projects.developer_id = 1 )
=> [#<Project:0x3257cc4
  @attributes=
  {"name"=>"ragi",
   "project_id"=>"1",
   "id"=>"1",
   "developer_id"=>"1",
   "created_at"=>nil}>,
 #<Project:0x3257c10
  @attributes=
  {"name"=>"acts_as_autenticated",
   "project_id"=>"3",
   "id"=>"3",
   "developer_id"=>"1",
   "created_at"=>nil}>]
has_many :through

    DHH’s
 One True Way
of Many to Many
has_many :through

Full Joiner Model
has_many :through
  class Appearance < ActiveRecord::Base
   belongs_to :dancer
   belongs_to :movie
  end

  class Dancer < ActiveRecord::Base
   has_many :appearances, :dependent => true
   has_many :movies, :through => :appearances
  end

  class Movie < ActiveRecord::Base
   has_many :appearances, :dependent => true
   has_many :dancers, :through => :appearances
  end
Validations
class User < ActiveRecord::Base

 validates_confirmation_of :login, :password

 validates_confirmation_of :email,

 
 :message => "should match confirmation"

 validates_format_of :email,

 
 :with => /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})/i,

 
 :on = :create
end
Validations
• Keeping Data Clean
• In object validation of fields, calculated
  validations
• Instead of key constraints
• The database is for storage, the model is for
  the business logic
• Kinds of validations, custom validations, etc...
But Wait?

• Aren’t format, presence, relationship
  validations supposed to be the database’s
  job?
• Traditionally, yes.
• ActiveRecord does constraints in the
  model, not the database
But Why?

• Validations  Constraints are Business Logic
• Business logic should be in the model
• It makes things easy
• End users can get useful error messages
• Makes the postback pattern work well
Data Integrity?
• It’s still possible to do constraints in the db
• But it’s not as necessary
• Validations are constraints which make
  sense in terms of functionality of the app
• The rails ways is to just use validations
• Most DBA’s insist on foreign_key
  constraints
What AR Returns?
• Arrays of Model Objects
• Preselects and instantiates objects
• Nifty methods: to_yaml, to_xml, to_json
Output Formats
ruby - inspect                                to_yaml
#Employee:0x36926a4                          --- !ruby/object:Employee
@attributes=                                  attributes:
 {manager_id=1,                            manager_id: 1
  id=1,                                    id: 1
  first_name=joe,                           first_name: joe
  last_name=schmo,                         last_name: schmo
  created_at=2007-04-21 09:08:59}         created_at: 2007-04-21 09:08:59


to_xml                                        to_json
?xml version=1.0 encoding=UTF-8?
                                              {attributes:
employee
                                              	    {manager_id: 1,
  created-at
                                              	    id: 1,
type=datetime2007-04-21T09:08:59-07:00/
created-at                                   	    first_name: joe,
  first-namejoe/first-name
                                              	    last_name: schmo,
  id type=integer1/id
                                              	    created_at: 2007-04-21 09:08:59}}
  last-nameschmo/last-name
  manager-id type=integer1/manager-id
/employee
Before  After
                            Callbacks
                                                             * (-) save
class Subscription  ActiveRecord::Base
                                                             * (-) valid?
  before_create :record_signup
                                                             * (1) before_validation
  private                                                    * (2) before_validation_on_create
   def record_signup                                         * (-) validate
     self.signed_up_on = Date.today
                                                             * (-) validate_on_create
   end
                                                             * (3) after_validation
 end
                                                             * (4) after_validation_on_create
                                                             * (5) before_save
 class Firm  ActiveRecord::Base
  # Destroys the associated clients and                      * (6) before_create
  #people when the firm is destroyed                          * (-) create
  before_destroy {                                           * (7) after_create

 |record| Person.destroy_all firm_id = #{record.id} }
                                                             * (8) after_save
  before_destroy {

 |record| Client.destroy_all client_of = #{record.id} }
 end
Optimizing AR

• Eager Loading
• Use Memecached
• Add index to your migrations
Security
Doing it Securely

class User  ActiveRecord::Base
  def self.authenticate_unsafely(user_name, password)
   find(:first, :conditions =
        user_name = '#{user_name}' AND password = '#{password}')
  end

 def self.authenticate_safely(user_name, password)
  find(:first, :conditions =
       [ user_name = ? AND password = ?, user_name, password ])
 end

 # Edge Rails Only (Rails 2.0)
 def self.authenticate_safely_simply(user_name, password)
  find(:first, :conditions =
       { :user_name = user_name, :password = password })
 end
end
Use The ActiveRecord Relationships
Anti-Pattern #1: Manually specifying the IDs when you construct the queries;
def show
 unless @todo_list = TodoList.find_by_id_and_user_id(params[:id], current_user.id)
 redirect_to '/'
end

Anti-Pattern #2: Querying globally, then checking ownership after the fact;
def show
 @todo_list = TodoList.find(params[:id])
 redirect_to '/' unless @todo_list.user_id = current_user.id
end

Anti-Pattern #3: Abusing with_scope for a this simple case either directly, or in an around_filter.
def show
 with_scope(:find={:user_id=current_user.id}) do
  @todo_list = TodoList.find(params[:id])
 end
end

Best Practice: The most effective way to do this is to call find on the todo_lists association.
def show
 @todo_list = current_user.todo_lists.find(params[:id])
end


         Examples Stolen From: http://www.therailsway.com/2007/3/26/association-proxies-are-your-friend
Create Via Association Proxies
The Bad Way
def create
 @todo_list = TodoList.new(params[:todo_list])
 @todo_list.user_id = current_user.id
 @todo_list.save!
 redirect_to todo_list_url(@todo_list)
end

A Better Way: Use association proxies for creation.
def create
 @todo_list = current_user.todo_lists.create! params[:todo_list]
 redirect_to todo_list_url(@todo_list)
end

The Best Practice - Handle exceptions for the user.
def create
 @todo_list = current_user.todo_lists.build params[:todo_list]
 if @todo_list.save
   redirect_to todo_list_url(@todo_list)
 else
   render :action='new'
 end
end     Examples Stolen From: http://www.therailsway.com/2007/3/26/association-proxies-are-your-friend
Special Fields
* created_at     * #{table_name}_count
                 * position
* created_on
                 * parent_id
* updated_at
                 * lft
* updated_on
                 * rgt
* lock_version
                 * quote
* type
                 * template
* id
Table Inheritance

Class Table Inheritance: Represents an inheritance
hierarchy of classes with one table for each class1.

Single Table Inheritance: Represents an inheritance
hierarchy of classes as a single table that has
columns for all the fields of the various classes2.

Concrete Table Inheritance: Represents an
inheritance hierarchy of classes with one table per
concrete class in the hierarchy
STI - Single Table Inheritance
     Represents an inheritance hierarchy of classes as a single
   table that has columns for all the fields of the various classes.
STI - Single Table Inheritance
                                            CREATE TABLE `companies` (
  class Company  ActiveRecord::Base; end
                                              `id` int(11) default NULL,
  class Firm  Company; end
                                              `name` varchar(255) default NULL,
  class Client  Company; end                 `type` varchar(32) default NULL
  class PriorityClient  Client; end        )




  Company.find(:first)
  SELECT * FROM companies LIMIT 1;

  Firm.find(:first)
   SELECT * FROM companies WHERE type = ‘firm’ LIMIT 1;
Legacy Databases




       How to do legacy databases with Active Record?

http://sl33p3r.free.fr/tutorials/rails/legacy/legacy_databases.html
Supporting Legacy DB’s
 class CustomerNote  ActiveRecord::Base

  set_primary_key client_comment_id
  set_sequence_name FooBarSequences

  def self.table_name() client_comment end

  def body
   read_attribute client_comment_body
  end

  def body=(value)
   write_attribute client_comment_body, value
  end
 end
   Thanks to: http://www.robbyonrails.com/articles/2005/07/25/the-legacy-of-databases-with-rails
Changing ActiveRecord
 Modify Active Record
  ActiveRecord::Base.table_name_prefix = my_
  ActiveRecord::Base.table_name_suffix = _table
  ActiveRecord::Base.pluralize_table_names = false

 Fixing the Auto-Increment / Sequence Problem
                                          module ActiveRecord
  module ActiveRecord
                                           module ConnectionAdapters
   class Base
                                            class MysqlAdapter
    class  self
                                              def prefetch_primary_key?(table_name = nil)
      def reset_sequence_name
                                               true
       #{table_name}_sequence
                                              end
      end
                                            end
    end
                                           end
   end
                                          end
  end




            Thanks to: http://fora.pragprog.com/rails-recipes/write-your-own/post/84
Changing ActiveRecord
 Telling ActiveRecord to fetch the primary key

  module ActiveRecord
   module ConnectionAdapters
    class MysqlAdapter

      def prefetch_primary_key?(table_name = nil)
       true
      end

      def next_sequence_value(sequence_name)
       sql = UPDATE #{ sequence_name} SET Id=LAST_INSERT_ID(Id+1);
       update(sql, #{sequence_name} Update)
       select_value(SELECT Id from #{ sequence_name},'Id')
      end

   end
  end

           Thanks to: http://fora.pragprog.com/rails-recipes/write-your-own/post/84
Ruby on Rails
 AR Alternatives



Ruby DataMapper
  iBatis - rBatis
Ruby DataMapper
http://rubyforge.org/projects/datamapper
  class FasterAuthor  DataMapper::Base

   set_table_name 'authors'

   property :name, :string, :size = 100
   property :url, :string, :size = 255
   property :is_active?, :boolean
   property :email, :string, :size = 255
   property :hashed_pass, :string, :size = 40
   property :created_at, :datetime
   property :modified_at, :datetime

   has_many :posts, :class = 'FasterPost' # :foreign_key = 'post_id'

   # prepends HTTP to a URL if necessary
   def self.prepend_http(url = '')
    if url and url != '' and not(url =~ /^http/i)
      url = 'http://' + url
    end
    return url
   end

  end
iBatis - rBatis
iBatis for Ruby (RBatis) is a port of Apache's iBatis library to Ruby
and Ruby on Rails. It is an O/R-mapper that allows for complete
customization of SQL. http://ibatis.apache.org




                 Not Very DRY / Rails Like
Drink the Kool aid?
Flickr Photos Used:
http://flickr.com/photos/brraveheart/114402291/
                                                    http://flickr.com/photos/ryangreenberg/57722319/
http://flickr.com/photos/bright/253175260/
                                                    http://flickr.com/photos/benandliz/11065337/
http://flickr.com/photos/good_day/63617697/
                                                    http://flickr.com/photos/gaspi/12944421/
http://flickr.com/photos/rickharris/416150393/
                                                    http://flickr.com/photos/thomashawk/221827536/
http://flickr.com/photos/babasteve/3322247/
                                                    http://flickr.com/photos/brianboulos/7707518/
http://flickr.com/photos/olivander/28058685/
                                                    http://flickr.com/photos/ross/28330560/
http://flickr.com/photos/brraveheart/44052308/
                                                    http://flickr.com/photos/emdot/45249090/
http://flickr.com/photos/ednothing/142393509/
                                                    http://flickr.com/photos/farhang/428136695/
http://flickr.com/photos/alltheaces/87505524/
                                                    http://flickr.com/photos/belljar/67877047/
http://flickr.com/photos/alfr3do/7436142/
                                                    http://flickr.com/photos/pulpolux/34545782/
http://flickr.com/photos/gdominici/57975123/
                                                    http://flickr.com/photos/monkeyc/107979135/
http://flickr.com/photos/josefstuefer/72512671/
                                                    http://flickr.com/photos/pedrosimoes7/449314732/
http://flickr.com/photos/uqbar/105440294/
                                                    http://flickr.com/photos/dincordero/405452471/
http://flickr.com/photos/auntiep/17135231/
                                                    http://flickr.com/photos/andidfl/203883534/
http://flickr.com/photos/einsame_spitze/406992131/
                                                    http://flickr.com/photos/ivanomak/434387836/
http://flickr.com/photos/beija-flor/63758047/
                                                    http://flickr.com/photos/nrvica/23858419/
http://flickr.com/photos/amerune/174617912/
                                                    http://flickr.com/photos/thespeak/137012632/
http://flickr.com/photos/hungry_i/47938311/
                                                    http://flickr.com/photos/thowi/31533027/
http://flickr.com/photos/santos/13952912/
                                                    http://flickr.com/photos/thelifeofbryan/468557520/
http://flickr.com/photos/supermietzi/179962496/
                                                    http://flickr.com/photos/eecue/289208982/
http://flickr.com/photos/traveller2020/206931940/
                                                    http://flickr.com/photos/estherase/14110154/
http://flickr.com/photos/ko_an/318906221/
                                                    http://flickr.com/photos/ehnmark/118117670/
Questions?

 Introduction to
  Active Record
    Evan ‘Rabble’ Henshaw-Plath
evan@protest.net - Yahoo! Brickhouse
 anarchogeek.com - testingrails.com

Más contenido relacionado

La actualidad más candente

QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...GeeksLab Odessa
 
New methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsNew methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsMikhail Egorov
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceNiraj Bharambe
 
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"GeeksLab Odessa
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's testsSean P. Floyd
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)Hendrik Ebbers
 
ORM2Pwn: Exploiting injections in Hibernate ORM
ORM2Pwn: Exploiting injections in Hibernate ORMORM2Pwn: Exploiting injections in Hibernate ORM
ORM2Pwn: Exploiting injections in Hibernate ORMMikhail Egorov
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash CourseColin O'Dell
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutDror Helper
 
JavaScript
JavaScriptJavaScript
JavaScriptSunil OS
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and EasybIakiv Kramarenko
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression LanguageDzmitry Naskou
 
Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecordscalaconfjp
 
Unit test candidate solutions
Unit test candidate solutionsUnit test candidate solutions
Unit test candidate solutionsbenewu
 
Mastering Oracle ADF Bindings
Mastering Oracle ADF BindingsMastering Oracle ADF Bindings
Mastering Oracle ADF BindingsEuegene Fedorenko
 

La actualidad más candente (19)

QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
 
New methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applicationsNew methods for exploiting ORM injections in Java applications
New methods for exploiting ORM injections in Java applications
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer science
 
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's tests
 
DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)DataFX 8 (JavaOne 2014)
DataFX 8 (JavaOne 2014)
 
ORM2Pwn: Exploiting injections in Hibernate ORM
ORM2Pwn: Exploiting injections in Hibernate ORMORM2Pwn: Exploiting injections in Hibernate ORM
ORM2Pwn: Exploiting injections in Hibernate ORM
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
PHP 7 Crash Course
PHP 7 Crash CoursePHP 7 Crash Course
PHP 7 Crash Course
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you about
 
Full Stack Unit Testing
Full Stack Unit TestingFull Stack Unit Testing
Full Stack Unit Testing
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
JavaFX Pitfalls
JavaFX PitfallsJavaFX Pitfalls
JavaFX Pitfalls
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression Language
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecord
 
Unit test candidate solutions
Unit test candidate solutionsUnit test candidate solutions
Unit test candidate solutions
 
Mastering Oracle ADF Bindings
Mastering Oracle ADF BindingsMastering Oracle ADF Bindings
Mastering Oracle ADF Bindings
 

Destacado

Plmce2012 scaling pinterest
Plmce2012 scaling pinterestPlmce2012 scaling pinterest
Plmce2012 scaling pinterestMohit Jain
 
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagramMohit Jain
 
UPenn on Rails pt 1
UPenn on Rails pt 1UPenn on Rails pt 1
UPenn on Rails pt 1Mat Schaffer
 
Phone Communities and Activism Showcase
Phone Communities and Activism ShowcasePhone Communities and Activism Showcase
Phone Communities and Activism ShowcaseRabble .
 
Liberating Location - Fire Eagle - Ecomm 2008
Liberating Location - Fire Eagle - Ecomm 2008Liberating Location - Fire Eagle - Ecomm 2008
Liberating Location - Fire Eagle - Ecomm 2008Rabble .
 
Introducción a Ruby on Rails
Introducción a Ruby on RailsIntroducción a Ruby on Rails
Introducción a Ruby on RailsDiego Algorta
 
Introducción a Ruby
Introducción a RubyIntroducción a Ruby
Introducción a RubyDiego Algorta
 
Building a Hacker Culture in Uruguay - OSCON 2011
Building a Hacker Culture in Uruguay - OSCON 2011Building a Hacker Culture in Uruguay - OSCON 2011
Building a Hacker Culture in Uruguay - OSCON 2011Rabble .
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails Mohit Jain
 
CoDesign CMS.362/CMS.862 MIT Evolution of Product Design
CoDesign CMS.362/CMS.862 MIT Evolution of Product DesignCoDesign CMS.362/CMS.862 MIT Evolution of Product Design
CoDesign CMS.362/CMS.862 MIT Evolution of Product DesignRabble .
 
Developing an Automated Testing Strategy
Developing an Automated Testing StrategyDeveloping an Automated Testing Strategy
Developing an Automated Testing StrategyJon Kruger
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Rabble .
 
Beyond Testing: Specs and Behavior Driven Development
Beyond Testing: Specs and Behavior  Driven DevelopmentBeyond Testing: Specs and Behavior  Driven Development
Beyond Testing: Specs and Behavior Driven DevelopmentRabble .
 
Sobre Hombros de Gigantes: Desarrollo de tecnología y la historia secreto de...
Sobre Hombros de Gigantes: Desarrollo de tecnología y  la historia secreto de...Sobre Hombros de Gigantes: Desarrollo de tecnología y  la historia secreto de...
Sobre Hombros de Gigantes: Desarrollo de tecnología y la historia secreto de...Rabble .
 
Mohit jain's resume
Mohit jain's resumeMohit jain's resume
Mohit jain's resumeMohit Jain
 

Destacado (15)

Plmce2012 scaling pinterest
Plmce2012 scaling pinterestPlmce2012 scaling pinterest
Plmce2012 scaling pinterest
 
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram
89025069 mike-krieger-instagram-at-the-airbnb-tech-talk-on-scaling-instagram
 
UPenn on Rails pt 1
UPenn on Rails pt 1UPenn on Rails pt 1
UPenn on Rails pt 1
 
Phone Communities and Activism Showcase
Phone Communities and Activism ShowcasePhone Communities and Activism Showcase
Phone Communities and Activism Showcase
 
Liberating Location - Fire Eagle - Ecomm 2008
Liberating Location - Fire Eagle - Ecomm 2008Liberating Location - Fire Eagle - Ecomm 2008
Liberating Location - Fire Eagle - Ecomm 2008
 
Introducción a Ruby on Rails
Introducción a Ruby on RailsIntroducción a Ruby on Rails
Introducción a Ruby on Rails
 
Introducción a Ruby
Introducción a RubyIntroducción a Ruby
Introducción a Ruby
 
Building a Hacker Culture in Uruguay - OSCON 2011
Building a Hacker Culture in Uruguay - OSCON 2011Building a Hacker Culture in Uruguay - OSCON 2011
Building a Hacker Culture in Uruguay - OSCON 2011
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
CoDesign CMS.362/CMS.862 MIT Evolution of Product Design
CoDesign CMS.362/CMS.862 MIT Evolution of Product DesignCoDesign CMS.362/CMS.862 MIT Evolution of Product Design
CoDesign CMS.362/CMS.862 MIT Evolution of Product Design
 
Developing an Automated Testing Strategy
Developing an Automated Testing StrategyDeveloping an Automated Testing Strategy
Developing an Automated Testing Strategy
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
 
Beyond Testing: Specs and Behavior Driven Development
Beyond Testing: Specs and Behavior  Driven DevelopmentBeyond Testing: Specs and Behavior  Driven Development
Beyond Testing: Specs and Behavior Driven Development
 
Sobre Hombros de Gigantes: Desarrollo de tecnología y la historia secreto de...
Sobre Hombros de Gigantes: Desarrollo de tecnología y  la historia secreto de...Sobre Hombros de Gigantes: Desarrollo de tecnología y  la historia secreto de...
Sobre Hombros de Gigantes: Desarrollo de tecnología y la historia secreto de...
 
Mohit jain's resume
Mohit jain's resumeMohit jain's resume
Mohit jain's resume
 

Similar a Introduction to Active Record at MySQL Conference 2007

Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Yasuko Ohba
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010Practical Ruby Projects with MongoDB - Ruby Kaigi 2010
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010Alex Sharp
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperGiordano Scalzo
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHPRob Knight
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecordMark Menard
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batisday
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Joao Lucas Santana
 
Active Record Inheritance in Rails
Active Record Inheritance in RailsActive Record Inheritance in Rails
Active Record Inheritance in RailsSandip Ransing
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQLddiers
 
Meet Magento Belarus debug Pavel Novitsky (eng)
Meet Magento Belarus debug Pavel Novitsky (eng)Meet Magento Belarus debug Pavel Novitsky (eng)
Meet Magento Belarus debug Pavel Novitsky (eng)Pavel Novitsky
 
Rails2 Pr
Rails2 PrRails2 Pr
Rails2 Prxibbar
 
Contagion的Ruby/Rails投影片
Contagion的Ruby/Rails投影片Contagion的Ruby/Rails投影片
Contagion的Ruby/Rails投影片cfc
 

Similar a Introduction to Active Record at MySQL Conference 2007 (20)

Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子Ruby on Rails ステップアップ講座 - 大場寧子
Ruby on Rails ステップアップ講座 - 大場寧子
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010Practical Ruby Projects with MongoDB - Ruby Kaigi 2010
Practical Ruby Projects with MongoDB - Ruby Kaigi 2010
 
DataMapper
DataMapperDataMapper
DataMapper
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Intro to Rails ActiveRecord
Intro to Rails ActiveRecordIntro to Rails ActiveRecord
Intro to Rails ActiveRecord
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batis
 
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
 
Active Record Inheritance in Rails
Active Record Inheritance in RailsActive Record Inheritance in Rails
Active Record Inheritance in Rails
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQL
 
Php summary
Php summaryPhp summary
Php summary
 
Meet Magento Belarus debug Pavel Novitsky (eng)
Meet Magento Belarus debug Pavel Novitsky (eng)Meet Magento Belarus debug Pavel Novitsky (eng)
Meet Magento Belarus debug Pavel Novitsky (eng)
 
SOLID Ruby SOLID Rails
SOLID Ruby SOLID RailsSOLID Ruby SOLID Rails
SOLID Ruby SOLID Rails
 
Rails2 Pr
Rails2 PrRails2 Pr
Rails2 Pr
 
Rails <form> Chronicle
Rails <form> ChronicleRails <form> Chronicle
Rails <form> Chronicle
 
Contagion的Ruby/Rails投影片
Contagion的Ruby/Rails投影片Contagion的Ruby/Rails投影片
Contagion的Ruby/Rails投影片
 

Más de Rabble .

La Historia Secreta de Twitter & El Modelo de los Lean Startups
La Historia Secreta de Twitter & El Modelo de los  Lean StartupsLa Historia Secreta de Twitter & El Modelo de los  Lean Startups
La Historia Secreta de Twitter & El Modelo de los Lean StartupsRabble .
 
Ruby Culture
Ruby CultureRuby Culture
Ruby CultureRabble .
 
Finding the Middle Way of Testing
Finding the Middle Way of TestingFinding the Middle Way of Testing
Finding the Middle Way of TestingRabble .
 
Hacking Frequent Flyer Programs
Hacking Frequent Flyer ProgramsHacking Frequent Flyer Programs
Hacking Frequent Flyer ProgramsRabble .
 
Desde Software Libre Hacia Datos Abiertos
Desde Software Libre Hacia Datos AbiertosDesde Software Libre Hacia Datos Abiertos
Desde Software Libre Hacia Datos AbiertosRabble .
 
Beyond REST? Building Data Services with XMPP PubSub
Beyond REST? Building Data Services with XMPP PubSubBeyond REST? Building Data Services with XMPP PubSub
Beyond REST? Building Data Services with XMPP PubSubRabble .
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails AppsRabble .
 

Más de Rabble . (7)

La Historia Secreta de Twitter & El Modelo de los Lean Startups
La Historia Secreta de Twitter & El Modelo de los  Lean StartupsLa Historia Secreta de Twitter & El Modelo de los  Lean Startups
La Historia Secreta de Twitter & El Modelo de los Lean Startups
 
Ruby Culture
Ruby CultureRuby Culture
Ruby Culture
 
Finding the Middle Way of Testing
Finding the Middle Way of TestingFinding the Middle Way of Testing
Finding the Middle Way of Testing
 
Hacking Frequent Flyer Programs
Hacking Frequent Flyer ProgramsHacking Frequent Flyer Programs
Hacking Frequent Flyer Programs
 
Desde Software Libre Hacia Datos Abiertos
Desde Software Libre Hacia Datos AbiertosDesde Software Libre Hacia Datos Abiertos
Desde Software Libre Hacia Datos Abiertos
 
Beyond REST? Building Data Services with XMPP PubSub
Beyond REST? Building Data Services with XMPP PubSubBeyond REST? Building Data Services with XMPP PubSub
Beyond REST? Building Data Services with XMPP PubSub
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
 

Último

The Economic History of the U.S. Lecture 17.pdf
The Economic History of the U.S. Lecture 17.pdfThe Economic History of the U.S. Lecture 17.pdf
The Economic History of the U.S. Lecture 17.pdfGale Pooley
 
Basic concepts related to Financial modelling
Basic concepts related to Financial modellingBasic concepts related to Financial modelling
Basic concepts related to Financial modellingbaijup5
 
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home Delivery
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home DeliveryPooja 9892124323 : Call Girl in Juhu Escorts Service Free Home Delivery
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home DeliveryPooja Nehwal
 
The Economic History of the U.S. Lecture 25.pdf
The Economic History of the U.S. Lecture 25.pdfThe Economic History of the U.S. Lecture 25.pdf
The Economic History of the U.S. Lecture 25.pdfGale Pooley
 
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...dipikadinghjn ( Why You Choose Us? ) Escorts
 
Booking open Available Pune Call Girls Wadgaon Sheri 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Wadgaon Sheri  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Wadgaon Sheri  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Wadgaon Sheri 6297143586 Call Hot Ind...Call Girls in Nagpur High Profile
 
03_Emmanuel Ndiaye_Degroof Petercam.pptx
03_Emmanuel Ndiaye_Degroof Petercam.pptx03_Emmanuel Ndiaye_Degroof Petercam.pptx
03_Emmanuel Ndiaye_Degroof Petercam.pptxFinTech Belgium
 
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service Nashik
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service NashikHigh Class Call Girls Nashik Maya 7001305949 Independent Escort Service Nashik
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
The Economic History of the U.S. Lecture 23.pdf
The Economic History of the U.S. Lecture 23.pdfThe Economic History of the U.S. Lecture 23.pdf
The Economic History of the U.S. Lecture 23.pdfGale Pooley
 
The Economic History of the U.S. Lecture 22.pdf
The Economic History of the U.S. Lecture 22.pdfThe Economic History of the U.S. Lecture 22.pdf
The Economic History of the U.S. Lecture 22.pdfGale Pooley
 
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdfFinTech Belgium
 
Log your LOA pain with Pension Lab's brilliant campaign
Log your LOA pain with Pension Lab's brilliant campaignLog your LOA pain with Pension Lab's brilliant campaign
Log your LOA pain with Pension Lab's brilliant campaignHenry Tapper
 
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )Pooja Nehwal
 
Booking open Available Pune Call Girls Talegaon Dabhade 6297143586 Call Hot ...
Booking open Available Pune Call Girls Talegaon Dabhade  6297143586 Call Hot ...Booking open Available Pune Call Girls Talegaon Dabhade  6297143586 Call Hot ...
Booking open Available Pune Call Girls Talegaon Dabhade 6297143586 Call Hot ...Call Girls in Nagpur High Profile
 
The Economic History of the U.S. Lecture 18.pdf
The Economic History of the U.S. Lecture 18.pdfThe Economic History of the U.S. Lecture 18.pdf
The Economic History of the U.S. Lecture 18.pdfGale Pooley
 
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...dipikadinghjn ( Why You Choose Us? ) Escorts
 
The Economic History of the U.S. Lecture 26.pdf
The Economic History of the U.S. Lecture 26.pdfThe Economic History of the U.S. Lecture 26.pdf
The Economic History of the U.S. Lecture 26.pdfGale Pooley
 
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...ssifa0344
 
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779Best VIP Call Girls Noida Sector 18 Call Me: 8448380779
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779Delhi Call girls
 
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...ssifa0344
 

Último (20)

The Economic History of the U.S. Lecture 17.pdf
The Economic History of the U.S. Lecture 17.pdfThe Economic History of the U.S. Lecture 17.pdf
The Economic History of the U.S. Lecture 17.pdf
 
Basic concepts related to Financial modelling
Basic concepts related to Financial modellingBasic concepts related to Financial modelling
Basic concepts related to Financial modelling
 
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home Delivery
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home DeliveryPooja 9892124323 : Call Girl in Juhu Escorts Service Free Home Delivery
Pooja 9892124323 : Call Girl in Juhu Escorts Service Free Home Delivery
 
The Economic History of the U.S. Lecture 25.pdf
The Economic History of the U.S. Lecture 25.pdfThe Economic History of the U.S. Lecture 25.pdf
The Economic History of the U.S. Lecture 25.pdf
 
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...
VIP Call Girl in Mira Road 💧 9920725232 ( Call Me ) Get A New Crush Everyday ...
 
Booking open Available Pune Call Girls Wadgaon Sheri 6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Wadgaon Sheri  6297143586 Call Hot Ind...Booking open Available Pune Call Girls Wadgaon Sheri  6297143586 Call Hot Ind...
Booking open Available Pune Call Girls Wadgaon Sheri 6297143586 Call Hot Ind...
 
03_Emmanuel Ndiaye_Degroof Petercam.pptx
03_Emmanuel Ndiaye_Degroof Petercam.pptx03_Emmanuel Ndiaye_Degroof Petercam.pptx
03_Emmanuel Ndiaye_Degroof Petercam.pptx
 
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service Nashik
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service NashikHigh Class Call Girls Nashik Maya 7001305949 Independent Escort Service Nashik
High Class Call Girls Nashik Maya 7001305949 Independent Escort Service Nashik
 
The Economic History of the U.S. Lecture 23.pdf
The Economic History of the U.S. Lecture 23.pdfThe Economic History of the U.S. Lecture 23.pdf
The Economic History of the U.S. Lecture 23.pdf
 
The Economic History of the U.S. Lecture 22.pdf
The Economic History of the U.S. Lecture 22.pdfThe Economic History of the U.S. Lecture 22.pdf
The Economic History of the U.S. Lecture 22.pdf
 
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf
06_Joeri Van Speybroek_Dell_MeetupDora&Cybersecurity.pdf
 
Log your LOA pain with Pension Lab's brilliant campaign
Log your LOA pain with Pension Lab's brilliant campaignLog your LOA pain with Pension Lab's brilliant campaign
Log your LOA pain with Pension Lab's brilliant campaign
 
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )
Vip Call US 📞 7738631006 ✅Call Girls In Sakinaka ( Mumbai )
 
Booking open Available Pune Call Girls Talegaon Dabhade 6297143586 Call Hot ...
Booking open Available Pune Call Girls Talegaon Dabhade  6297143586 Call Hot ...Booking open Available Pune Call Girls Talegaon Dabhade  6297143586 Call Hot ...
Booking open Available Pune Call Girls Talegaon Dabhade 6297143586 Call Hot ...
 
The Economic History of the U.S. Lecture 18.pdf
The Economic History of the U.S. Lecture 18.pdfThe Economic History of the U.S. Lecture 18.pdf
The Economic History of the U.S. Lecture 18.pdf
 
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...
VIP Call Girl Service Andheri West ⚡ 9920725232 What It Takes To Be The Best ...
 
The Economic History of the U.S. Lecture 26.pdf
The Economic History of the U.S. Lecture 26.pdfThe Economic History of the U.S. Lecture 26.pdf
The Economic History of the U.S. Lecture 26.pdf
 
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...
Solution Manual for Financial Accounting, 11th Edition by Robert Libby, Patri...
 
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779Best VIP Call Girls Noida Sector 18 Call Me: 8448380779
Best VIP Call Girls Noida Sector 18 Call Me: 8448380779
 
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...
Solution Manual for Principles of Corporate Finance 14th Edition by Richard B...
 

Introduction to Active Record at MySQL Conference 2007

  • 1. Introduction to Active Record Evan ‘Rabble’ Henshaw-Plath evan@protest.net - Yahoo! Brickhouse anarchogeek.com - testingrails.com
  • 2. Active Record is a Design Pattern An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
  • 3. Active Record the Pattern Person last_name first_name dependents_count insert update get_exemption is_flagged_for_audit? get_taxable_earnings? Active Record uses the most obvious approach, putting data access logic in the domain object. - Martin Fowler
  • 4. One Class Per Table The Model Code The Database class User < ActiveRecord::Base CREATE TABLE `users` ( `id` int(11) NOT NULL auto_increment, end `login` varchar(255), `email` varchar(255), `crypted_password` varchar(40), `salt` varchar(40), `created_at` datetime default NULL, `updated_at` datetime default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;
  • 6. There Are Other Ways To Do it Active Record is just one ‘Data Source Architectural Pattern’ • Table Data Gateway • Row Data Gateway • Data Mapper • The Anti-Patterns
  • 7. Standard Active Record • Direct mapping to the DB • Class to table • Object to row • Simple, no relationship between objects • Just a finder method with getters and setters
  • 8. ActiveRecord the ruby library Active Record is a library built for Ruby on Rails. Makes CRUD Easy Create Read Update Delete
  • 9. ActiveRecord the ruby library I have never seen an Active Record implementation as complete or as useful as rails. - Martin Fowler
  • 10. Rails’ ActiveRecord • DRY Conventions & Assumptions • Validations • Before and after filters • Database Agnostic (mostly) • Migrations • Model relationships • has_many, belongs_to, etc...
  • 11. What Active Record Likes • mapping class names to table names • pluralized table names • integer primary keys • classname_id foreign keys • simple schemas • single table inheritance
  • 12. Active Record Doesn’t Like • views • stored procedures • foreign key constraints • cascading commits • split or clustered db’s • enums
  • 13. The Basics ./app/models/user.rb Loading a user class User < ActiveRecord::Base >> user_obj = User.find(2) end => #<User:0x352e8bc @attributes= {"salt"=>"d9ef...", The SQL Log "updated_at"=>"2007-04-19 10:49:15", "crypted_password"=>"9c1...", User Load (0.003175) "id"=>"2", SELECT * FROM users "remember_token"=>"a8d...", WHERE (users.id = 2) LIMIT 1 "login"=>"rabble", "created_at"=>"2007-04-19 10:49:15", "email"=>"evan@protest.net"}>
  • 14. The Find Method Find is the primary method of Active Record Examples: User.find(23) User.find(:first) User.find(:all, :offset => 10, :limit => 10) User.find(:all, :include => [:account, :friends]) User.find(:all, :conditions => [“category in (?), categories, :limit => 50) User.find(:first).articles
  • 15. The Four Ways of Find Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). Find first: This will return the first record matched by the options used. Find all: This will return all the records matched by the options used. Indirectly: The find method is used for AR lookups via associations.
  • 16. Understanding Find Model#find(:all, { parameters hash } What Find Does: * generates sql * executes sql * returns an enumerable (array like object) * creates an AR model object for each row
  • 17. Find with :conditions :conditions - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. Student.find(:all, :conditions => [‘first_name = ? and status = ?’ ‘rabble’, 1]) New Style (Edge Rails Only) Student.find(:all, :conditions => {:first_name => “rabble”, :status => 1}) SQL Executed: SELECT * FROM students WHERE (first_name = 'rabble' and status = 1);
  • 18. Order By :order - An SQL fragment like "created_at DESC, name". Student.find(:all, :order => ‘updated_at DESC’) SQL Executed: SELECT * FROM users ORDER BY created_at;
  • 19. Group By :group - An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. Student.find(:all, :group => ‘graduating_class’) SQL Executed: SELECT * FROM users GROUP BY graduating_class;
  • 20. Limit & Offset :limit - An integer determining the limit on the number of rows that should be returned. :offset- An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. Student.find(:all, :limit => 10, :offset => 0) SQL Executed: SELECT * FROM users LIMIT 0, 10;
  • 21. Joins :joins - An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed). Student.find(:all, :join => "LEFT JOIN comments ON comments.post_id = id") SQL Executed: SELECT users.* FROM users, comments LEFT JOIN comments ON comments.post_id = users.id; Returns read only objects unless you say :readonly => false
  • 23. Associations The Four Primary Associations belongs_to has_one has_many has_and_belongs_to_many class Project < ActiveRecord::Base belongs_to :portfolio has_one :project_manager has_many :milestones has_and_belongs_to_many :categories end
  • 24. Associations One to One has_one & belongs_to Many to One has_many & belongs_to Many to Many has_and_belongs_to_many has_many :through
  • 25. One to One Use has_one in the base, and belongs_to in the associated model. class Employee < ActiveRecord::Base has_one :office end class Office < ActiveRecord::Base belongs_to :employee # foreign key - employee_id end
  • 26. One To One Example >> joe_employee = Employee.find_by_first_name('joe') SELECT * FROM employees WHERE (employees.`first_name` = 'joe') LIMIT 1 => #<Employee:0x36beb14 @attributes={"id"=>"1", "first_name"=>"joe", "last_name"=>"schmo", "created_at"=>"2007-04-21 09:08:59"}> >> joes_office = joe_employee.office SELECT * FROM offices WHERE (offices.employee_id = 1) LIMIT 1 => #<Office:0x36bc06c @attributes={"employee_id"=>"1", "id"=>"1", "created_at"=>"2007-04-21 09:11:44", "location"=>"A4302"}> >> joes_office.employee SELECT * FROM employees WHERE (employees.`id` = 1) => #<Employee:0x36b6ef0 @attributes={"id"=>"1", "first_name"=>"joe", "last_name"=>"schmo", "created_at"=>"2007-04-21 09:08:59"}>
  • 27. belongs_to One to One Relationship. Use belong to when the foreign key is in THIS table. • Post#author (similar to Author.find(author_id) ) • Post#author=(author) (similar to post.author_id = author.id) • Post#author? (similar to post.author == some_author) • Post#author.nil? • Post#build_author (similar to post.author = Author.new) • Post#create_author (similar to post.author = Author; post.author.save;
  • 28. Defining belongs_to class Employee < ActiveRecord::Base belongs_to :firm, :foreign_key => "client_of" belongs_to :author, :class_name => "Person", :foreign_key => "author_id" belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", :conditions => 'discounts > #{payments_count}' belongs_to :attachable, :polymorphic => true end
  • 29. has_one One to One Relationship. Use has_one when the foreign key is in the OTHER table. • Account#beneficiary (similar to Beneficiary.find (:first, :conditions => "account_id = #{id}")) • Account#beneficiary=(beneficiary) (similar to beneficiary.account_id = account.id; beneficiary.save) • Account#beneficiary.nil? • Account#build_beneficiary (similar to Beneficiary.new ("account_id" => id)) • Account#create_beneficiary (similar to b = Beneficiary.new("account_id" => id); b.save; b)
  • 30. Defining has_one class Employee < ActiveRecord::Base # destroys the associated credit card has_one :credit_card, :dependent => :destroy # updates the associated records foreign key value to null rather than destroying it has_one :credit_card, :dependent => :nullify has_one :last_comment, :class_name => "Comment", :order => "posted_on" has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" has_one :attachment, :as => :attachable end
  • 31. One to Many One-to-many Use has_many in the base, and belongs_to in the associated model. class Manager < ActiveRecord::Base has_many :employees end class Employee < ActiveRecord::Base belongs_to :manager # foreign key - manager_id end
  • 32. One to Many >> benevolent_dictator = Manager.find(:first, :conditions => ['name = "DHH"']) SELECT * FROM managers WHERE (name = "DHH") LIMIT 1 => #<Manager:0x369b7b8 @attributes={"name"=>"DHH", "id"=>"1", "created_at"=>"2007-04-21 09:59:24"}> >> minions = benevolent_dictator.employees SELECT * FROM employees WHERE (employees.manager_id = 1) => [#<Employee:0x36926a4 @attributes={"manager_id"=>"1", "id"=>"1", "first_name"=>"joe", "last_name"=>"schmo", "created_at"=>"2007-04-21 09:08:59"}>, #<Employee:0x36925f0 @attributes={"manager_id"=>"1", "id"=>"2", "first_name"=>"funky", "last_name"=>"monkey", "created_at"=>"2007-04-21 09:58:20"}>]
  • 33. has_many Augmenting the Model • Firm#clients (similar to Clients.find :all, :conditions => "firm_id = #{id}") • Firm#clients<< • Firm#clients.delete • Firm#client_ids • Firm#client_ids= • Firm#clients=
  • 34. has_many • Firm#client.clear • Firm#clients.empty? (similar to firm.clients.size == 0) • Firm#clients.size (similar to Client.count "firm_id = #{id}") • Firm#clients.find (similar to Client.find(id, :conditions => "firm_id = #{id}")) • Firm#clients.build (similar to Client.new ("firm_id" => id)) • Firm#clients.create (similar to c = Client.new ("firm_id" => id); c.save; c)
  • 35. has_many examples class Employee < ActiveRecord::Base has_many :comments, :order => "posted_on" has_many :comments, :include => :author has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name" has_many :tracks, :order => "position", :dependent => :destroy has_many :comments, :dependent => :nullify has_many :tags, :as => :taggable has_many :subscribers, :through => :subscriptions, :source => :user has_many :subscribers, :class_name => "Person", :finder_sql => 'SELECT DISTINCT people.* ' + 'FROM people p, post_subscriptions ps ' + 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + 'ORDER BY p.first_name' end
  • 36. Many to Many Simple Joiner Table has_and_belongs_to_many Joiner Model has_many :through
  • 37. has_and_belongs_to_many The Simple Joiner Table Way
  • 39. has_and_belongs_to_many Augmenting the Model • Developer#projects • Developer#projects<< • Developer#projects.delete • Developer#projects= • Developer#projects_ids • Developer#projects_ids= • Developer#clear
  • 40. has_and_belongs_to_many • Developer#projects.empty? • Developer#projects.size • Developer#projects.find(id) # Also find(:first / :all) • Developer#projects.build #(similar to Project.new ("project_id" => id)) • Developer#projects.create (similar to c = Project.new("project_id" => id); c.save; c)
  • 41. habtm example create_table :developers do |t| t.column :name, :string t.column :created_at, :datetime end create_table :projects do |t| t.column :name, :string t.column :created_at, :datetime end create_table(:developers_projects, :id => false) do |t| t.column :developer_id, :integer t.column :project_id, :integer end
  • 42. habtm example >> d = Developer.find(1) SELECT * FROM developers WHERE (developers.`id` = 1) => #<Developer:0x32bc7dc @attributes={"name"=>"rabble", "id"=>"1", "created_at"=>nil}> >> d.projects SELECT * FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE (developers_projects.developer_id = 1 ) => [#<Project:0x3257cc4 @attributes= {"name"=>"ragi", "project_id"=>"1", "id"=>"1", "developer_id"=>"1", "created_at"=>nil}>, #<Project:0x3257c10 @attributes= {"name"=>"acts_as_autenticated", "project_id"=>"3", "id"=>"3", "developer_id"=>"1", "created_at"=>nil}>]
  • 43. has_many :through DHH’s One True Way of Many to Many
  • 45. has_many :through class Appearance < ActiveRecord::Base belongs_to :dancer belongs_to :movie end class Dancer < ActiveRecord::Base has_many :appearances, :dependent => true has_many :movies, :through => :appearances end class Movie < ActiveRecord::Base has_many :appearances, :dependent => true has_many :dancers, :through => :appearances end
  • 46. Validations class User < ActiveRecord::Base validates_confirmation_of :login, :password validates_confirmation_of :email, :message => "should match confirmation" validates_format_of :email, :with => /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})/i, :on = :create end
  • 47. Validations • Keeping Data Clean • In object validation of fields, calculated validations • Instead of key constraints • The database is for storage, the model is for the business logic • Kinds of validations, custom validations, etc...
  • 48. But Wait? • Aren’t format, presence, relationship validations supposed to be the database’s job? • Traditionally, yes. • ActiveRecord does constraints in the model, not the database
  • 49. But Why? • Validations Constraints are Business Logic • Business logic should be in the model • It makes things easy • End users can get useful error messages • Makes the postback pattern work well
  • 50. Data Integrity? • It’s still possible to do constraints in the db • But it’s not as necessary • Validations are constraints which make sense in terms of functionality of the app • The rails ways is to just use validations • Most DBA’s insist on foreign_key constraints
  • 51. What AR Returns? • Arrays of Model Objects • Preselects and instantiates objects • Nifty methods: to_yaml, to_xml, to_json
  • 52. Output Formats ruby - inspect to_yaml #Employee:0x36926a4 --- !ruby/object:Employee @attributes= attributes: {manager_id=1, manager_id: 1 id=1, id: 1 first_name=joe, first_name: joe last_name=schmo, last_name: schmo created_at=2007-04-21 09:08:59} created_at: 2007-04-21 09:08:59 to_xml to_json ?xml version=1.0 encoding=UTF-8? {attributes: employee {manager_id: 1, created-at id: 1, type=datetime2007-04-21T09:08:59-07:00/ created-at first_name: joe, first-namejoe/first-name last_name: schmo, id type=integer1/id created_at: 2007-04-21 09:08:59}} last-nameschmo/last-name manager-id type=integer1/manager-id /employee
  • 53. Before After Callbacks * (-) save class Subscription ActiveRecord::Base * (-) valid? before_create :record_signup * (1) before_validation private * (2) before_validation_on_create def record_signup * (-) validate self.signed_up_on = Date.today * (-) validate_on_create end * (3) after_validation end * (4) after_validation_on_create * (5) before_save class Firm ActiveRecord::Base # Destroys the associated clients and * (6) before_create #people when the firm is destroyed * (-) create before_destroy { * (7) after_create |record| Person.destroy_all firm_id = #{record.id} } * (8) after_save before_destroy { |record| Client.destroy_all client_of = #{record.id} } end
  • 54. Optimizing AR • Eager Loading • Use Memecached • Add index to your migrations
  • 56. Doing it Securely class User ActiveRecord::Base def self.authenticate_unsafely(user_name, password) find(:first, :conditions = user_name = '#{user_name}' AND password = '#{password}') end def self.authenticate_safely(user_name, password) find(:first, :conditions = [ user_name = ? AND password = ?, user_name, password ]) end # Edge Rails Only (Rails 2.0) def self.authenticate_safely_simply(user_name, password) find(:first, :conditions = { :user_name = user_name, :password = password }) end end
  • 57. Use The ActiveRecord Relationships Anti-Pattern #1: Manually specifying the IDs when you construct the queries; def show unless @todo_list = TodoList.find_by_id_and_user_id(params[:id], current_user.id) redirect_to '/' end Anti-Pattern #2: Querying globally, then checking ownership after the fact; def show @todo_list = TodoList.find(params[:id]) redirect_to '/' unless @todo_list.user_id = current_user.id end Anti-Pattern #3: Abusing with_scope for a this simple case either directly, or in an around_filter. def show with_scope(:find={:user_id=current_user.id}) do @todo_list = TodoList.find(params[:id]) end end Best Practice: The most effective way to do this is to call find on the todo_lists association. def show @todo_list = current_user.todo_lists.find(params[:id]) end Examples Stolen From: http://www.therailsway.com/2007/3/26/association-proxies-are-your-friend
  • 58. Create Via Association Proxies The Bad Way def create @todo_list = TodoList.new(params[:todo_list]) @todo_list.user_id = current_user.id @todo_list.save! redirect_to todo_list_url(@todo_list) end A Better Way: Use association proxies for creation. def create @todo_list = current_user.todo_lists.create! params[:todo_list] redirect_to todo_list_url(@todo_list) end The Best Practice - Handle exceptions for the user. def create @todo_list = current_user.todo_lists.build params[:todo_list] if @todo_list.save redirect_to todo_list_url(@todo_list) else render :action='new' end end Examples Stolen From: http://www.therailsway.com/2007/3/26/association-proxies-are-your-friend
  • 59. Special Fields * created_at * #{table_name}_count * position * created_on * parent_id * updated_at * lft * updated_on * rgt * lock_version * quote * type * template * id
  • 60. Table Inheritance Class Table Inheritance: Represents an inheritance hierarchy of classes with one table for each class1. Single Table Inheritance: Represents an inheritance hierarchy of classes as a single table that has columns for all the fields of the various classes2. Concrete Table Inheritance: Represents an inheritance hierarchy of classes with one table per concrete class in the hierarchy
  • 61. STI - Single Table Inheritance Represents an inheritance hierarchy of classes as a single table that has columns for all the fields of the various classes.
  • 62. STI - Single Table Inheritance CREATE TABLE `companies` ( class Company ActiveRecord::Base; end `id` int(11) default NULL, class Firm Company; end `name` varchar(255) default NULL, class Client Company; end `type` varchar(32) default NULL class PriorityClient Client; end ) Company.find(:first) SELECT * FROM companies LIMIT 1; Firm.find(:first) SELECT * FROM companies WHERE type = ‘firm’ LIMIT 1;
  • 63. Legacy Databases How to do legacy databases with Active Record? http://sl33p3r.free.fr/tutorials/rails/legacy/legacy_databases.html
  • 64. Supporting Legacy DB’s class CustomerNote ActiveRecord::Base set_primary_key client_comment_id set_sequence_name FooBarSequences def self.table_name() client_comment end def body read_attribute client_comment_body end def body=(value) write_attribute client_comment_body, value end end Thanks to: http://www.robbyonrails.com/articles/2005/07/25/the-legacy-of-databases-with-rails
  • 65. Changing ActiveRecord Modify Active Record ActiveRecord::Base.table_name_prefix = my_ ActiveRecord::Base.table_name_suffix = _table ActiveRecord::Base.pluralize_table_names = false Fixing the Auto-Increment / Sequence Problem module ActiveRecord module ActiveRecord module ConnectionAdapters class Base class MysqlAdapter class self def prefetch_primary_key?(table_name = nil) def reset_sequence_name true #{table_name}_sequence end end end end end end end end Thanks to: http://fora.pragprog.com/rails-recipes/write-your-own/post/84
  • 66. Changing ActiveRecord Telling ActiveRecord to fetch the primary key module ActiveRecord module ConnectionAdapters class MysqlAdapter def prefetch_primary_key?(table_name = nil) true end def next_sequence_value(sequence_name) sql = UPDATE #{ sequence_name} SET Id=LAST_INSERT_ID(Id+1); update(sql, #{sequence_name} Update) select_value(SELECT Id from #{ sequence_name},'Id') end end end Thanks to: http://fora.pragprog.com/rails-recipes/write-your-own/post/84
  • 67. Ruby on Rails AR Alternatives Ruby DataMapper iBatis - rBatis
  • 68. Ruby DataMapper http://rubyforge.org/projects/datamapper class FasterAuthor DataMapper::Base set_table_name 'authors' property :name, :string, :size = 100 property :url, :string, :size = 255 property :is_active?, :boolean property :email, :string, :size = 255 property :hashed_pass, :string, :size = 40 property :created_at, :datetime property :modified_at, :datetime has_many :posts, :class = 'FasterPost' # :foreign_key = 'post_id' # prepends HTTP to a URL if necessary def self.prepend_http(url = '') if url and url != '' and not(url =~ /^http/i) url = 'http://' + url end return url end end
  • 69. iBatis - rBatis iBatis for Ruby (RBatis) is a port of Apache's iBatis library to Ruby and Ruby on Rails. It is an O/R-mapper that allows for complete customization of SQL. http://ibatis.apache.org Not Very DRY / Rails Like
  • 71. Flickr Photos Used: http://flickr.com/photos/brraveheart/114402291/ http://flickr.com/photos/ryangreenberg/57722319/ http://flickr.com/photos/bright/253175260/ http://flickr.com/photos/benandliz/11065337/ http://flickr.com/photos/good_day/63617697/ http://flickr.com/photos/gaspi/12944421/ http://flickr.com/photos/rickharris/416150393/ http://flickr.com/photos/thomashawk/221827536/ http://flickr.com/photos/babasteve/3322247/ http://flickr.com/photos/brianboulos/7707518/ http://flickr.com/photos/olivander/28058685/ http://flickr.com/photos/ross/28330560/ http://flickr.com/photos/brraveheart/44052308/ http://flickr.com/photos/emdot/45249090/ http://flickr.com/photos/ednothing/142393509/ http://flickr.com/photos/farhang/428136695/ http://flickr.com/photos/alltheaces/87505524/ http://flickr.com/photos/belljar/67877047/ http://flickr.com/photos/alfr3do/7436142/ http://flickr.com/photos/pulpolux/34545782/ http://flickr.com/photos/gdominici/57975123/ http://flickr.com/photos/monkeyc/107979135/ http://flickr.com/photos/josefstuefer/72512671/ http://flickr.com/photos/pedrosimoes7/449314732/ http://flickr.com/photos/uqbar/105440294/ http://flickr.com/photos/dincordero/405452471/ http://flickr.com/photos/auntiep/17135231/ http://flickr.com/photos/andidfl/203883534/ http://flickr.com/photos/einsame_spitze/406992131/ http://flickr.com/photos/ivanomak/434387836/ http://flickr.com/photos/beija-flor/63758047/ http://flickr.com/photos/nrvica/23858419/ http://flickr.com/photos/amerune/174617912/ http://flickr.com/photos/thespeak/137012632/ http://flickr.com/photos/hungry_i/47938311/ http://flickr.com/photos/thowi/31533027/ http://flickr.com/photos/santos/13952912/ http://flickr.com/photos/thelifeofbryan/468557520/ http://flickr.com/photos/supermietzi/179962496/ http://flickr.com/photos/eecue/289208982/ http://flickr.com/photos/traveller2020/206931940/ http://flickr.com/photos/estherase/14110154/ http://flickr.com/photos/ko_an/318906221/ http://flickr.com/photos/ehnmark/118117670/
  • 72. Questions? Introduction to Active Record Evan ‘Rabble’ Henshaw-Plath evan@protest.net - Yahoo! Brickhouse anarchogeek.com - testingrails.com