[ANN] Active Record 0.9.1: More naturalness, new license

Discussion in 'Ruby' started by David Heinemeier Hansson, Jul 29, 2004.

  1. What's new in Active Record 0.9.1?
    ==================================

    This is a minor update that brings more natural object-style accessing
    to has_and_belongs_to_many and has_many. It also changed the license to
    MIT license.

    Download from http://activerecord.rubyonrails.org, talk on #rubyonrails
    (FreeNet).


    * Added natural object-style assignment for has_and_belongs_to_many
    associations.
    Consider the following model:

    class Event < ActiveRecord::Base
    has_one_and_belongs_to_many :sponsors
    end

    class Sponsor < ActiveRecord::Base
    has_one_and_belongs_to_many :sponsors
    end

    Earlier, you'd have to use synthetic methods for creating
    associations between two objects of the above class:

    roskilde_festival.add_to_sponsors(carlsberg)
    roskilde_festival.remove_from_sponsors(carlsberg)

    nike.add_to_events(world_cup)
    nike.remove_from_events(world_cup)

    Now you can use regular array-styled methods:

    roskilde_festival.sponsors << carlsberg
    roskilde_festival.sponsors.delete(carlsberg)

    nike.events << world_cup
    nike.events.delete(world_cup)

    * Added delete method for has_many associations. Using this will
    nullify an association between the has_many and the belonging
    object by setting the foreign key to null. Consider this model:

    class Post < ActiveRecord::Base
    has_many :comments
    end

    class Comment < ActiveRecord::Base
    belongs_to :post
    end

    You could do something like:

    funny_comment.has_post? # => true
    announcement.comments.delete(funny_comment)
    funny_comment.has_post? # => false


    What about Active Record 1.0.0?
    ==================================

    Active Record will be moving to promised land of 1.0.0 within a
    reasonably short time frame. So if you have any wishes, comments, or
    complaints, you'll want to voice them sooner rather than later. 1.0.0
    won't mean the end of developement, of course, but it would be nice to
    have a really solid release. So do speak forth.


    Call for help!
    ==============

    Do you have working knowledge with and access to either Oracle, ODBC,
    Sybase, or DB2, I'd be really grateful if you would consider writing an
    adapter for Active Record. Adapters are usually just around 100 lines
    of code. You'll have three examples to look at, a well-specified
    interface[1], and almost 100 test cases to make it real easy. Luke
    Holden reports that he spent just a few hours getting SQLite and
    PostgreSQL adapters working.

    [1] http://ar.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/
    AbstractAdapter.html


    Active Record -- Object-relation mapping put on rails
    =====================================================

    Active Record connects business objects and database tables to create a
    persistable
    domain model where logic and data is presented in one wrapping. It's an
    implementation of the object-relational mapping (ORM) pattern by the
    same name as described by Martin Fowler:

    "An object that wraps a row in a database table or view, encapsulates
    the database access, and adds domain logic on that data."

    Active Records main contribution to the pattern is to relieve the
    original of two stunting problems: lack of associations and
    inheritance. By adding a simple domain language-like set of macros to
    describe the former and integrating the Single Table Inheritance
    pattern for the latter, Active Record narrows the gap of functionality
    between the data mapper and active record approach.

    A short rundown of the major features:

    * Automated mapping between classes and tables, attributes and columns.
    class Product < ActiveRecord::Base; end

    ...is automatically mapped to the table named "products", such as:

    CREATE TABLE products (
    id int(11) NOT NULL auto_increment,
    name varchar(255),
    PRIMARY KEY (id)
    );

    ...which again gives Product#name and Product#name=(new_name)


    * Associations between objects controlled by simple meta-programming
    macros.
    class Firm < ActiveRecord::Base
    has_many :clients
    has_one :account
    belong_to :conglomorate
    end


    * Aggregations of value objects controlled by simple meta-programming
    macros.
    class Account < ActiveRecord::Base
    composed_of :balance, :class_name => "Money",
    :mapping => %w(balance amount)
    composed_of :address,
    :mapping => [%w(address_street street),
    %w(address_city city)]
    end


    * Validation rules that can differ for new or existing objects.
    class Post < ActiveRecord::Base
    def validate # validates on both creates and updates
    errors.add_on_empty "title"
    end

    def validate_on_update
    errors.add_on_empty "password"
    end
    end


    * Callbacks as methods or ques on the entire lifecycle
    (instantiation, saving, destroying, validating, etc).

    class Person < ActiveRecord::Base
    def before_destroy # is called just before Person#destroy
    CreditCard.find(credit_card_id).destroy
    end
    end

    class Account < ActiveRecord::Base
    after_find :eager_load, 'self.class.announce(#{id})'
    end

    Learn more in link:classes/ActiveRecord/Callbacks.html


    * Observers for the entire lifecycle
    class CommentObserver < ActiveRecord::Observer
    def after_create(comment) # is called just after Comment#save
    NotificationService.send_email("",
    comment)
    end
    end


    * Inheritance hierarchies
    class Company < ActiveRecord::Base; end
    class Firm < Company; end
    class Client < Company; end
    class PriorityClient < Client; end


    * Transaction support on both a database and object level. The latter
    is implemented
    by using Transaction::Simple

    # Just database transaction
    Account.transaction do
    david.withdrawal(100)
    mary.deposit(100)
    end

    # Database and object transaction
    Account.transaction(david, mary) do
    david.withdrawal(100)
    mary.deposit(100)
    end


    * Direct manipulation (instead of service invocation)

    So instead of (Hibernate example):

    long pkId = 1234;
    DomesticCat pk = (DomesticCat) sess.load( Cat.class, new
    Long(pkId) );
    // something interesting involving a cat...
    sess.save(cat);
    sess.flush(); // force the SQL INSERT

    Active Record lets you:

    pkId = 1234
    cat = Cat.find(pkId)
    # something even more interesting involving a the same cat...
    cat.save


    * Database abstraction through simple adapters (~100 lines) with a
    shared connector

    ActiveRecord::Base.establish_connection:)adapter => "sqlite",
    :dbfile => "dbfile")

    ActiveRecord::Base.establish_connection(
    :adapter => "mysql",
    :host => "localhost",
    :username => "me",
    :password => "secret",
    :database => "activerecord"
    )


    * Logging support for Log4r and Logger

    ActiveRecord::Base.logger = Logger.new(STDOUT)
    ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")


    Philosophy
    ==========

    Active Record attempts to provide a coherent wrapping for the
    inconvenience that is object-relational mapping. The prime directive
    for this mapping has been to minimize the amount of code needed to
    built a real-world domain model. This is made possible by relying on a
    number of conventions that make it easy for Active Record to infer
    complex relations and structures from a minimal amount of explicit
    direction.

    Convention over Configuration:
    * No XML-files!
    * Lots of reflection and run-time extension
    * Magic is not inherently a bad word

    Admit the Database:
    * Lets you drop down to SQL for odd cases and performance
    * Doesn't attempt to duplicate or replace data definitions

    --
    David Heinemeier Hansson,
    http://www.rubyonrails.org/ -- Web-application framework for Ruby
    http://www.instiki.org/ -- A No-Step-Three Wiki in Ruby
    http://www.basecamphq.com/ -- Web-based Project Management
    http://www.loudthinking.com/ -- Broadcasting Brain
    http://www.nextangle.com/ -- Development & Consulting Services
     
    David Heinemeier Hansson, Jul 29, 2004
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Volker Grabsch
    Replies:
    2
    Views:
    764
    Michael Hudson
    Jul 25, 2005
  2. Frits van Soldt

    How to insert a new record in detailsview when there are no record

    Frits van Soldt, Nov 16, 2005, in forum: ASP .Net Web Controls
    Replies:
    2
    Views:
    832
    Frits van Soldt
    Nov 17, 2005
  3. Maximus
    Replies:
    2
    Views:
    208
    Bob Barrows [MVP]
    Apr 12, 2007
  4. David Heinemeier Hansson
    Replies:
    2
    Views:
    191
    Michael Neumann
    May 31, 2004
  5. David Heinemeier Hansson
    Replies:
    14
    Views:
    234
    Joel VanderWerf
    Jul 28, 2004
Loading...

Share This Page