SlideShare une entreprise Scribd logo
1  sur  56
Introduction to ActiveRecord ,[object Object],[object Object]
Rails ActiveRecord ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Definition © Vita Rara, Inc. Active Record: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. -Martin Fowler, Patterns of Enterprise Application Architecture (page 160)
Rails ActiveRecord ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
A Leaky Abstraction ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Fundamentals ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
ActiveRecord Model Example © Vita Rara, Inc. create_table  &quot;persons&quot;   do  |t|  t.string :first_name, last_name t.timestamps  end class  Person < ActiveRecord::Base end p = Person.new p.first_name = ‘Mark’ p.last_name = ‘Menard’ p.save
Working with Legacy Schemas ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
CRUD: Create, Read, Update, Delete ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
ActiveRecord::Base.new © Vita Rara, Inc. # Instantiate a new Person, which can be persisted. p  =  Person. new p.save # Instantiate a new Person, with attributes set based on a # Map, which can be persisted. p  =  Person. new (:first_name =>  'Mark' , :last_name =>  'Menard' ) p.save
ActiveRecord::Base.create © Vita Rara, Inc. # Immediated create a record in the database. p  =  Person.create(:first_name =>  'Mark' , :last_name =>  'Menard' ) # This sets the attributes and calls #save on the instance.
Finding Models ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Advanced Finding ,[object Object],© Vita Rara, Inc. User.find(:all,  :conditions => [ “login  =   ?  AND password  =   ?” , login, password], :limit =>  10 , :offset =>  10 , :order =>  'login' , :joins =>  'accounts on user.account_id = accounts.id' )
Advanced Finding (con’t) ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Eager Loading: Avoid N+1 Issue © Vita Rara, Inc. <%  # Don't put code like this in your view. This is for illustration only! # Find and display order summary of all pending orders for an account. orders  =  Order.find_pending_by_account(current_account) %> <% orders.each  do  |order| -%> <%= render :partial =>  'order_header'  %> <!-- This fires off a query for each order! BAD BAD BAD --> <% order.line_items.each  do  |line_item| -%> <%= render :partial =>  'line_item'  %> <%  end  -%> <%  end  -%> <%  # Better would be orders  =  Order.find_pending_by_account(current_account,  :include => [ :line_items ]) %>
Updating Models © Vita Rara, Inc. user  =  User.find( 1 ) user.first_name  =  ‘Mark’ user.save # returns true on success user.last_name  =  ‘Menard’ user.save! # throws an exception if it fails # Immediately update the attributes and call #save # returns true on success user.update_attributes(:first_name =>  'John' ,  :last_name =>  'Doe' ) # Immediately update the attributes and call #save! # throws an exception on failure. user.update_attributes!(:password =>  ‘abccd1234’ )
Transactions ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
ActiveRecord Associations
ActiveRecord Associations ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Association Methods ,[object Object],[object Object],[object Object],© Vita Rara, Inc.
ActiveRecord Association Examples © Vita Rara, Inc. # Has Many class  Order < ActiveRecord::Base has_many :order_line_items end class  OrderLineItem < ActiveRecord::Base belongs_to :order end # Has One class  Party < ActiveRecord::Base has_one :login_credential end class  LoginCredential < ActiveRecord::Base belongs_to :party end
has_many & belongs_to ,[object Object],[object Object],© Vita Rara, Inc. class  Order < ActiveRecord::Base   has_many :line_items end class  LineItem < ActiveRecord::Base   belongs_to :order end create_table :orders  do  |t|   t.string :number end create_table :line_items  do  |t|   t.integer :order_id end
Has Many Examples © Vita Rara, Inc. has_many :comments, :order =>  &quot;posted_on&quot;   has_many :comments, :include => :author  has_many :people, :class_name =>  &quot;Person&quot; ,    :conditions =>  &quot;deleted = 0&quot; , :order =>  &quot;name&quot;   has_many :tracks, :order =>  &quot;position&quot; , :dependent => :destroy  has_many :comments, :dependent => :nullify  has_many :tags, :as => :taggable  has_many :subscribers, :through => :subscriptions, :source => :user  has_many :subscribers, :class_name =>  &quot;Person&quot; , :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'
has_many Methods © Vita Rara, Inc. class  Firm   has_many :clients end firm  =  Firm.find( 1 ) firm.clients firm.clients <<   firm.clients.delete  firm.clients =   firm.client_ids  firm.client_ids =   firm.clients.clear  firm.clients.empty? firm.clients.count  firm.clients.find firm.clients.build(:first_name =>  'Mark' ) # Like Party.new(:firm_id => firm.id) firm.clients.create(:first_name =>  'Mark' ) # Like Party.create(:firm_id => firm.id)
has_and_belongs_to_many ,[object Object],© Vita Rara, Inc. create_table :categories_posts, :id => false  do    t.column :category_id, :integer, :null => false    t.column :post_id, :integer, :null => false  end   class  Product < ActiveRecord::Base   has_and_belongs_to_many :categories end class  Category < ActiveRecord::Base   has_and_belongs_to_many :products end product  =  Product.find_by_name(“Mac Book Pro”) category  =  Category.find_by_name(“Laptops”)  product.categories.count # => 0  category.products.count # => 0  product.categories  <<  category  product.categories.count # => 1  category.products.count # => 1
Join Models vs. has_and_belongs_to_many ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
has_many :foos, :through => :bars ,[object Object],© Vita Rara, Inc. class  Blog < ActiveRecord::Base   has_many :subscriptions   has_many :users, :through => :subscriptions end class  User < ActiveRecord::Base has_many :subscriptions has_many :blogs, :through => :subscriptions end class  Subscription < ActiveRecord::Base   belongs_to :blog   belongs_to :user end
Polymorphic Associations ,[object Object],© Vita Rara, Inc. class  Person < ActiveRecord::Base   has_one :address, :as => :addressable end class  Company < ActiveRecord::Base   has_one :address, :as => :addressable end class  Address < ActiveRecord::Base   belongs_to :addressable, :polymorphic => true end create_table :addresses  do  |t|   # ...   t.integer :addressable_id   t.string  :addressable_type end
ActiveRecord Validations ,[object Object]
Validation ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Validation Callbacks ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Validation Callbacks (cont) © Vita Rara, Inc. class  Person < ActiveRecord::Base  def   validate   puts “validate invoked”  end   def   validate_on_create   puts “validate_on_create invoked”  end   def   validate_on_update   puts “validate_on_update invoked”  end   end   peter  =  Person.create(:name => “Peter”)  # => peter.validate and peter.validate_on_create invoked  peter.last_name  =  “Forsberg”  peter.save # => peter.validate_on_update invoked
Declarative Validations © Vita Rara, Inc. Rails contains a large number of declarative validations that are applied to classes by convention. Declarative validations free developers from the drudgery of most model validation.
validates_presence_of ,[object Object],© Vita Rara, Inc. class  Person < ActiveRecord::Base   validates_presence_of :first_name   validates_presence_of :last_name end p  =  Person. new p.valid? #=> false p.first_name  =   'Mark' p.last_name  =   'Menard' p.valid? #=> true
validates_uniqueness_of ,[object Object],[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base belongs_to :account   validates_uniqueness_of :login, :scope => [ :account ] end account = Account.find(1) user_1  =  account.users.create(:login =>  'mark' ) user_2  =  account.users.create!(:login =>  'mark' ) #=> Throws InvalidRecord exceptoion
validates_numericality_of ,[object Object],[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base   validates_numericality_of :number, :integer_only => true end User.create!(:number =>  'some number' ) #=> Throws Invalid
validates_length_of ,[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base   validates_length_of :login, :within =>  3 .. 20   validates_length_of :password, :is =>  8   validates_length_of :name, :minimum =>  3 end
validates_format_of ,[object Object],[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base   validates_format_of :email, :with =>  /^[]+$/ end
validates_inclusion_of & validates_exclusion_of ,[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base   validates_inclusion_of :gender, :in =>  %w( male female ) ,  :message =>  &quot;Oh really....&quot; validates_exclusion_of :login, :in =>  %w( root admin super ) ,  :message =>  &quot;Tisk tisk...&quot; end
validates_associated ,[object Object],© Vita Rara, Inc. class  User < ActiveRecord::Base   belongs_to :account   validates_associated :account, :on => :create end class  Account < ActiveRecord::Base   validates_presence_of :name end user  =  User. new (:login =>  'mark' , :name =>  'Mark Menard' ) user.account  =  Account. new  # invalid missing name user.save! #=> Throws RecordInvalid exception.
Other Declarative Validations ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc. You can also create your own declarative validations that match your problem domain.
Using Validation Callbacks ,[object Object],[object Object],[object Object],© Vita Rara, Inc. class  Account   validate :does_domain_exist     private     def   does_domain_exist   Resolv.getaddress(self.domain_name)   rescue   errors.add(:domain_name,  'Domain name does not exist.' )   end end
Using Validation Callbacks ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Model Life Cycle
New Model Callbacks ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Existing Model Callbacks ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Destroy Model Callbacks ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Callback Use Cases ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Cleaning up Attributes Prior to Saving © Vita Rara, Inc. class  CreditCard   before_validation :cleanup_number     private     def   cleanup_number   self.number  =  number.gsub( /[^0-9]/ ,  &quot;&quot; ) true  # I like to be explicit   end end
Observers
Observers ,[object Object],[object Object],[object Object],© Vita Rara, Inc.
Creating an Audit Trail with an Observer © Vita Rara, Inc. # in config/environment.rb config.active_record_observers  =  [ :auditor ] # in auditor.rb class  Auditor < ActiveRecord::Observer   observe User     def   after_create  (model)   log_info( &quot;New #{model.class.name} created.&quot; , model)   end     def   after_update  (model)   log_info( &quot;Update #{model.class.name}&quot; , model)   end     def   after_destroy  (model)   log_info( &quot;Destroy #{model.class.name}&quot; , model)   end     private     def   log_info  (model, info)   log.info(info)   log.info(model.inspect)   end end
Shameless Self Promotion
Ruby and Rails Training ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Ruby on Rails Consulting ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.
Contact Information ,[object Object],[object Object],[object Object],[object Object],© Vita Rara, Inc.

Contenu connexe

Tendances

Apache Sling : JCR, OSGi, Scripting and REST
Apache Sling : JCR, OSGi, Scripting and RESTApache Sling : JCR, OSGi, Scripting and REST
Apache Sling : JCR, OSGi, Scripting and REST
Carsten Ziegeler
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django Introduction
Ganga Ram
 

Tendances (20)

Javascript
JavascriptJavascript
Javascript
 
Event In JavaScript
Event In JavaScriptEvent In JavaScript
Event In JavaScript
 
Javascript
JavascriptJavascript
Javascript
 
Introduction of Html/css/js
Introduction of Html/css/jsIntroduction of Html/css/js
Introduction of Html/css/js
 
Basics of JavaScript
Basics of JavaScriptBasics of JavaScript
Basics of JavaScript
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
React state
React  stateReact  state
React state
 
Introduction to the Web API
Introduction to the Web APIIntroduction to the Web API
Introduction to the Web API
 
Javascript basics
Javascript basicsJavascript basics
Javascript basics
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Regular Expressions in Java
Regular Expressions in JavaRegular Expressions in Java
Regular Expressions in Java
 
Introduction to JavaScript Basics.
Introduction to JavaScript Basics.Introduction to JavaScript Basics.
Introduction to JavaScript Basics.
 
Control Structures In Php 2
Control Structures In Php 2Control Structures In Php 2
Control Structures In Php 2
 
Xml http request
Xml http requestXml http request
Xml http request
 
Apache Sling : JCR, OSGi, Scripting and REST
Apache Sling : JCR, OSGi, Scripting and RESTApache Sling : JCR, OSGi, Scripting and REST
Apache Sling : JCR, OSGi, Scripting and REST
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django Introduction
 
Ruby on Rails Presentation
Ruby on Rails PresentationRuby on Rails Presentation
Ruby on Rails Presentation
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
Dom(document object model)
Dom(document object model)Dom(document object model)
Dom(document object model)
 
JavaScript - Chapter 11 - Events
 JavaScript - Chapter 11 - Events  JavaScript - Chapter 11 - Events
JavaScript - Chapter 11 - Events
 

Similaire à Intro to Rails ActiveRecord

OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
Nhibernatethe Orm For Net Platform 1226744632929962 8
Nhibernatethe Orm For Net Platform 1226744632929962 8Nhibernatethe Orm For Net Platform 1226744632929962 8
Nhibernatethe Orm For Net Platform 1226744632929962 8
Nicolas Thon
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
Samnang Chhun
 
Debugging and Error handling
Debugging and Error handlingDebugging and Error handling
Debugging and Error handling
Suite Solutions
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On Rails
Wen-Tien Chang
 

Similaire à Intro to Rails ActiveRecord (20)

Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on RailsBoston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on Rails
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 
Intro to Ruby on Rails
Intro to Ruby on RailsIntro to Ruby on Rails
Intro to Ruby on Rails
 
Extending MySQL Enterprise Monitor
Extending MySQL Enterprise MonitorExtending MySQL Enterprise Monitor
Extending MySQL Enterprise Monitor
 
DynamicRecord Presentation
DynamicRecord PresentationDynamicRecord Presentation
DynamicRecord Presentation
 
Nhibernatethe Orm For Net Platform 1226744632929962 8
Nhibernatethe Orm For Net Platform 1226744632929962 8Nhibernatethe Orm For Net Platform 1226744632929962 8
Nhibernatethe Orm For Net Platform 1226744632929962 8
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
 
Debugging and Error handling
Debugging and Error handlingDebugging and Error handling
Debugging and Error handling
 
Jasig Rubyon Rails
Jasig Rubyon RailsJasig Rubyon Rails
Jasig Rubyon Rails
 
Compass Framework
Compass FrameworkCompass Framework
Compass Framework
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On Rails
 
Framework
FrameworkFramework
Framework
 
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 EnglishGrails 0.3-SNAPSHOT Presentation WJAX 2006 English
Grails 0.3-SNAPSHOT Presentation WJAX 2006 English
 
Intro Open Social and Dashboards
Intro Open Social and DashboardsIntro Open Social and Dashboards
Intro Open Social and Dashboards
 
WordPress development paradigms, idiosyncrasies and other big words
WordPress development paradigms, idiosyncrasies and other big wordsWordPress development paradigms, idiosyncrasies and other big words
WordPress development paradigms, idiosyncrasies and other big words
 
Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007
 
Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009
 

Plus de Mark Menard

Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013
Mark Menard
 
Mobile Platforms and App Development
Mobile Platforms and App DevelopmentMobile Platforms and App Development
Mobile Platforms and App Development
Mark Menard
 

Plus de Mark Menard (14)

Let's Do Some Upfront Design - WindyCityRails 2014
Let's Do Some Upfront Design - WindyCityRails 2014Let's Do Some Upfront Design - WindyCityRails 2014
Let's Do Some Upfront Design - WindyCityRails 2014
 
A Tour of Wyriki
A Tour of WyrikiA Tour of Wyriki
A Tour of Wyriki
 
Small Code - RailsConf 2014
Small Code - RailsConf 2014Small Code - RailsConf 2014
Small Code - RailsConf 2014
 
Small Code - Ruby on Ales 2014
Small Code - Ruby on Ales 2014Small Code - Ruby on Ales 2014
Small Code - Ruby on Ales 2014
 
Write Small Things (Code)
Write Small Things (Code)Write Small Things (Code)
Write Small Things (Code)
 
JRuby 6 Years in Production
JRuby 6 Years in ProductionJRuby 6 Years in Production
JRuby 6 Years in Production
 
Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013Conference of Grand Masters Tech Talk 2013
Conference of Grand Masters Tech Talk 2013
 
Startup Lessons Learned
Startup Lessons LearnedStartup Lessons Learned
Startup Lessons Learned
 
Mobile Platforms and App Development
Mobile Platforms and App DevelopmentMobile Platforms and App Development
Mobile Platforms and App Development
 
Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2Ruby on Rails Training - Module 2
Ruby on Rails Training - Module 2
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
Behavior Driven Development with Rails
Behavior Driven Development with RailsBehavior Driven Development with Rails
Behavior Driven Development with Rails
 
JRuby in a Java World
JRuby in a Java WorldJRuby in a Java World
JRuby in a Java World
 

Intro to Rails ActiveRecord

  • 1.
  • 2.
  • 3. Definition © Vita Rara, Inc. Active Record: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. -Martin Fowler, Patterns of Enterprise Application Architecture (page 160)
  • 4.
  • 5.
  • 6.
  • 7. ActiveRecord Model Example © Vita Rara, Inc. create_table &quot;persons&quot; do |t| t.string :first_name, last_name t.timestamps end class Person < ActiveRecord::Base end p = Person.new p.first_name = ‘Mark’ p.last_name = ‘Menard’ p.save
  • 8.
  • 9.
  • 10. ActiveRecord::Base.new © Vita Rara, Inc. # Instantiate a new Person, which can be persisted. p = Person. new p.save # Instantiate a new Person, with attributes set based on a # Map, which can be persisted. p = Person. new (:first_name => 'Mark' , :last_name => 'Menard' ) p.save
  • 11. ActiveRecord::Base.create © Vita Rara, Inc. # Immediated create a record in the database. p = Person.create(:first_name => 'Mark' , :last_name => 'Menard' ) # This sets the attributes and calls #save on the instance.
  • 12.
  • 13.
  • 14.
  • 15. Eager Loading: Avoid N+1 Issue © Vita Rara, Inc. <% # Don't put code like this in your view. This is for illustration only! # Find and display order summary of all pending orders for an account. orders = Order.find_pending_by_account(current_account) %> <% orders.each do |order| -%> <%= render :partial => 'order_header' %> <!-- This fires off a query for each order! BAD BAD BAD --> <% order.line_items.each do |line_item| -%> <%= render :partial => 'line_item' %> <% end -%> <% end -%> <% # Better would be orders = Order.find_pending_by_account(current_account, :include => [ :line_items ]) %>
  • 16. Updating Models © Vita Rara, Inc. user = User.find( 1 ) user.first_name = ‘Mark’ user.save # returns true on success user.last_name = ‘Menard’ user.save! # throws an exception if it fails # Immediately update the attributes and call #save # returns true on success user.update_attributes(:first_name => 'John' , :last_name => 'Doe' ) # Immediately update the attributes and call #save! # throws an exception on failure. user.update_attributes!(:password => ‘abccd1234’ )
  • 17.
  • 19.
  • 20.
  • 21. ActiveRecord Association Examples © Vita Rara, Inc. # Has Many class Order < ActiveRecord::Base has_many :order_line_items end class OrderLineItem < ActiveRecord::Base belongs_to :order end # Has One class Party < ActiveRecord::Base has_one :login_credential end class LoginCredential < ActiveRecord::Base belongs_to :party end
  • 22.
  • 23. Has Many Examples © Vita Rara, Inc. has_many :comments, :order => &quot;posted_on&quot; has_many :comments, :include => :author has_many :people, :class_name => &quot;Person&quot; , :conditions => &quot;deleted = 0&quot; , :order => &quot;name&quot; has_many :tracks, :order => &quot;position&quot; , :dependent => :destroy has_many :comments, :dependent => :nullify has_many :tags, :as => :taggable has_many :subscribers, :through => :subscriptions, :source => :user has_many :subscribers, :class_name => &quot;Person&quot; , :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'
  • 24. has_many Methods © Vita Rara, Inc. class Firm has_many :clients end firm = Firm.find( 1 ) firm.clients firm.clients << firm.clients.delete firm.clients = firm.client_ids firm.client_ids = firm.clients.clear firm.clients.empty? firm.clients.count firm.clients.find firm.clients.build(:first_name => 'Mark' ) # Like Party.new(:firm_id => firm.id) firm.clients.create(:first_name => 'Mark' ) # Like Party.create(:firm_id => firm.id)
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32. Validation Callbacks (cont) © Vita Rara, Inc. class Person < ActiveRecord::Base def validate puts “validate invoked” end def validate_on_create puts “validate_on_create invoked” end def validate_on_update puts “validate_on_update invoked” end end peter = Person.create(:name => “Peter”) # => peter.validate and peter.validate_on_create invoked peter.last_name = “Forsberg” peter.save # => peter.validate_on_update invoked
  • 33. Declarative Validations © Vita Rara, Inc. Rails contains a large number of declarative validations that are applied to classes by convention. Declarative validations free developers from the drudgery of most model validation.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49. Cleaning up Attributes Prior to Saving © Vita Rara, Inc. class CreditCard before_validation :cleanup_number private def cleanup_number self.number = number.gsub( /[^0-9]/ , &quot;&quot; ) true # I like to be explicit end end
  • 51.
  • 52. Creating an Audit Trail with an Observer © Vita Rara, Inc. # in config/environment.rb config.active_record_observers = [ :auditor ] # in auditor.rb class Auditor < ActiveRecord::Observer observe User def after_create (model) log_info( &quot;New #{model.class.name} created.&quot; , model) end def after_update (model) log_info( &quot;Update #{model.class.name}&quot; , model) end def after_destroy (model) log_info( &quot;Destroy #{model.class.name}&quot; , model) end private def log_info (model, info) log.info(info) log.info(model.inspect) end end
  • 54.
  • 55.
  • 56.

Notes de l'éditeur

  1. This definition supposes a relational data store. The active record pattern would not apply to document oriented systems such as CouchDB, Mongo, and other No-SQL databases, as they tend to store aggregates.
  2. I rarely use these options. :select can lead to confusion if you select columns from more than one table because the returned objects will be read-only. I have yet to find a common use case for :group
  3. Many times complex views will want to be backed by a custom finder to avoid N+1 issues. I usually place these in a finder module mixed into my model class to keep the model class clean.
  4. This is where we begin joining models to other models to reflect the domain space.
  5. I very rarely use this type of association. I find that my join models eventually begin to a
  6. To halt the chain return false. To continue return true.