Neues in ActiveRecord 1.14.0

Scott Raymond sagt

Und jetzt zum lustigen Teil!

Assoziationen

Drei Glanzlichter der neuen Version:

has_many :through

Englische Erklärungen dazu gibt es im Rails-Wiki und auf matthewman.net.

Beispiel:
class Author < ActiveRecord::Base
  has_many :authorships
  has_many :books, :through => :authorships
end
class Book < ActiveRecord::Base
  has_many :authorships
  has_many :authors, :through => :authorships
end
class Authorship < ActiveRecord::Base
  belongs_to :author
  belongs_to :book
end
Author.find(:first).books.find(:all, :include => :reviews)

Polymorphe Assoziationen

Siehe Understanding Polymorphic Associations.

Polymorphe Assoziationen werden gebraucht, wenn ein Model belongs_to-Assoziationen zu mehreren Models hat:

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end
class User < ActiveRecord::Base
  has_one :address, :as => :addressable
end
class Company < ActiveRecord::Base
  has_one :address, :as => :addressable
end

Realisiert wird dieses Beispiel mit einer zusätzlichen Spalte addressable_type in der Tabelle addresses.

:through + :polymorphic = ?

has_many :through-Assoziationen unterstützen keinen polymorphen Zugriff auf das assoziierte Objekt. “has_many :through” hat dazu einen (englischen) Artikel.

Standardoptionen

...für find-Aufrufe bei has_(and_belongs_to_)many-Assoziationen.

Zum Beispiel:

class Post
  has_many :recent_comments, :class_name => "Comment", :limit => 10, :include => :author
end

post.recent_comments.find(:all)
# benutzt LIMIT 10 und läd authors mit
post.recent_comments.find(:all, :limit => nil)
# benutzt kein LIMIT, läd aber authors mit

:dependent

Die :dependent-Option wurde geändert:

  • Statt :dependent => true gibt man nun :dependent => :destroy an.
  • :exclusively_dependent => true heißt jetzt :dependent => :delete_all
  • :dependent => :nullify leert alle assoziierten Objekte.

Validations

validate_uniqueness_of über mehrere Spalten

Ein Lehrer kann pro Schuljahr nur eine Klasse unterrichten:
class LehrPlan < ActiveRecord::Base
  validates_uniqueness_of :lehrer_id, :scope => [:jahr, :klasse_id]
end

Sonstiges

Kaskadierendes Eager-Loading

Anfragen wie Author.find :all, :include => { :posts => :comments } holen in einem einzigen Query alle Autoren, ihre Posts und die Kommentare, die zu diesen Posts gehören.

Beispiel:

Author.find :all, :include => {:posts=>:comments}
Author.find :all, :include => [ {:posts=>:comments}, :categorizations ]
Author.find :all, :include => { :posts => [:comments, :categorizations] }
Company.find :all, :include => { :groups => {:members=>:favorites} }

Verschachteltes with_scope

Siehe API-Dokumentation und habtm.com.

Developer.with_scope(:find => { :conditions => "salary > 10000", :limit => 10 }) do
  Developer.find(:all)
  #-> SELECT * FROM developers WHERE (salary > 10000) LIMIT 10
  # inner rule is used. (all previous parameters are ignored)
  Developer.with_exclusive_scope(:find => { :conditions => "name = 'Jamis'" }) do
    Developer.find(:all)
    #-> SELECT * FROM developers WHERE (name = 'Jamis')
  end
  # parameters are merged
  Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do
    Developer.find(:all)
    #-> SELECT * FROM developers WHERE (( salary > 10000 ) AND ( name = 'Jamis' )) LIMIT 10
  end
end

Berechnungen

Für einfache Berechnungen braucht man nun kein SQL mehr:

Person.count :all, :conditions => ["age > ?", 26]
Person.average :age
Person.minimum :salary
Person.maximum :age
Person.sum :salary, :group => :last_name

XML-Repräsentationen für Records

topic.to_xml
topic.to_xml :skip_instruct => true,
  :skip_attributes => [:id, bonus_time, :written_on, replies_count]
firm.to_xml :include => [:account, :clients]

Im Zusammenspiel mit den to_xml-Erweiterungen für Array und Hash kann man so Daten ganz einfach in XML verwandeln.

Fixture-Unterverzeichnisse

Fixtures können jetzt in Unterverzeichnissen von test/fixtures gespeichert werden. Ideal zum Organisieren von Fixtures für STI.

ActiveRecord::Errors

ActiveRecord::Errors ist jetzt Enumerable, bietet also Methoden wie each, select, inject und group_by.

Bugfixes

  • validates_length_of funktioniert jetzt auch für UTF-8-Strings.
  • Dynamische find-Methoden wie find_by_name_and_hair_color benutzen jetzt die Zusatzbedingenungen, die man ihnen via :conditions übergibt, wie man es erwartet.