Rails 3 Model: Difference between revisions

From Wiki
Jump to navigation Jump to search
No edit summary
Line 1: Line 1:
= Define the Model =
== Associations ==
=== One-to-one ===
<source lang="ruby">
class User < ActiveRecord::Base
    has_one :profile          # creates User.profile method
end                           
-------------------------------
class Profile < ActiveRecord::Base
    belongs_to :user          # assumes Profile.user_id column
end                            # creates Profile.user method
</source>
REMINDER: the <code>belongs_to</code> declaration always goes in the class with the foreign key
==== has_one automatic methods ====
<source lang="ruby">
user.profile #=> #<Profile id: 2, user_id: 1, ...>
user.profile.nil? #=> false
user.build_profile(:bio => 'eats leaves') #=> #<Profile id: nil, user_id: 1, ...>  # not automatically saved
user.create_profile(:bio => 'eats leaves') #=> #<Profile id: 3, user_id: 1, ...>    # automatically saved
</source>
==== has_one options ====
<source lang="ruby">
has_one :profile, :class_name => 'Account'      # refer to user.account instead of user.profile
has_one :profile, :foreign_key => 'account_id'  # refer to user.account instead of user.profile
has_one :profile, :conditions => "active = 1"  # only specific profiles are considered
has_one :profile, :dependent => :destroy        # call destroy on profile when user is destroyed, also ":delete" and ":nullify"
</source>
=== One-to-many ===
<source lang="ruby">
class User < ActiveRecord::Base
    has_many :articles          # creates User.articles method
end
-------------------------------
class Article < ActiveRecord::Base
    belongs_to :user            # assumes Article.user_id column
end                              # creates Article.user method
</source>
==== has_many automatic methods ====
<source lang="ruby">
user.articles.size              # array length
user.article_ids                # list of ids
user.articles << Article.first  # automatically saves association in Article.user_id
user.articles.delete(articles)  # remove articles by setting Article.user_id to null
user.articles.clear              # remove all articles by setting Article.user_id to null
user.articles.find(conditions)  # find a subset of user.articles
user.articles.build(:title => 'Ruby 1.9')  # return associated article but don't save yet
user.articles.create(:title => 'Ruby 1.9')  # return associated article that has already been saved
</source>
==== has_many options ====
<source lang="ruby">
has_many :articles, :class_name => 'Post'          # refer to user.posts instead of user.articles
has_many :articles, :foreign_key => 'post_id'      # refer to user.posts instead of user.articles
has_many :articles, :conditions => "active = 1"    # only consider specific articles
has_many :articles, :order => "published_at DESC"  # default order of user.articles
has_many :articles, :dependent => :destroy        # destroy article when user is destroyed, also ":delete" and ":nullify"
</source>
= Work with Model Objects =


== Create and Save ==
== Create and Save ==
Line 62: Line 126:
article.errors.on(:title)    # "can't be blank"
article.errors.on(:title)    # "can't be blank"
article.valid?                # false
article.valid?                # false
</source>
== Associations ==
=== One-to-one ===
<source lang="ruby">
class User < ActiveRecord::Base
    has_one :profile          # creates User.profile method
end                           
-------------------------------
class Profile < ActiveRecord::Base
    belongs_to :user          # assumes Profile.user_id column
end                            # creates Profile.user method
</source>
REMINDER: the <code>belongs_to</code> declaration always goes in the class with the foreign key
==== has_one automatic methods ====
<source lang="ruby">
user.profile #=> #<Profile id: 2, user_id: 1, ...>
user.profile.nil? #=> false
user.build_profile(:bio => 'eats leaves') #=> #<Profile id: nil, user_id: 1, ...>  # not automatically saved
user.create_profile(:bio => 'eats leaves') #=> #<Profile id: 3, user_id: 1, ...>    # automatically saved
</source>
==== has_one options ====
<source lang="ruby">
has_one :profile, :class_name => 'Account'      # refer to user.account instead of user.profile
has_one :profile, :foreign_key => 'account_id'  # refer to user.account instead of user.profile
has_one :profile, :conditions => "active = 1"  # only specific profiles are considered
has_one :profile, :dependent => :destroy        # call destroy on profile when user is destroyed, also ":delete" and ":nullify"
</source>
=== One-to-many ===
<source lang="ruby">
class User < ActiveRecord::Base
    has_many :articles          # creates User.articles method
end
-------------------------------
class Article < ActiveRecord::Base
    belongs_to :user            # assumes Article.user_id column
end                              # creates Article.user method
</source>
==== has_many automatic methods ====
<source lang="ruby">
user.articles.size              # array length
user.article_ids                # list of ids
user.articles << Article.first  # automatically saves association in Article.user_id
user.articles.delete(articles)  # remove articles by setting Article.user_id to null
user.articles.clear              # remove all articles by setting Article.user_id to null
user.articles.find(conditions)  # find a subset of user.articles
user.articles.build(:title => 'Ruby 1.9')  # return associated article but don't save yet
user.articles.create(:title => 'Ruby 1.9')  # return associated article that has already been saved
</source>
==== has_many options ====
<source lang="ruby">
has_many :articles, :class_name => 'Post'          # refer to user.posts instead of user.articles
has_many :articles, :foreign_key => 'post_id'      # refer to user.posts instead of user.articles
has_many :articles, :conditions => "active = 1"    # only consider specific articles
has_many :articles, :order => "published_at DESC"  # default order of user.articles
has_many :articles, :dependent => :destroy        # destroy article when user is destroyed, also ":delete" and ":nullify"
</source>
</source>

Revision as of 22:35, 28 June 2011

Define the Model

Associations

One-to-one

class User < ActiveRecord::Base
    has_one :profile           # creates User.profile method
end                            
-------------------------------
class Profile < ActiveRecord::Base 
    belongs_to :user           # assumes Profile.user_id column
end                            # creates Profile.user method

REMINDER: the belongs_to declaration always goes in the class with the foreign key

has_one automatic methods

user.profile #=> #<Profile id: 2, user_id: 1, ...> 
user.profile.nil? #=> false 
user.build_profile(:bio => 'eats leaves') #=> #<Profile id: nil, user_id: 1, ...>   # not automatically saved
user.create_profile(:bio => 'eats leaves') #=> #<Profile id: 3, user_id: 1, ...>    # automatically saved

has_one options

has_one :profile, :class_name => 'Account'      # refer to user.account instead of user.profile
has_one :profile, :foreign_key => 'account_id'  # refer to user.account instead of user.profile
has_one :profile, :conditions => "active = 1"   # only specific profiles are considered
has_one :profile, :dependent => :destroy        # call destroy on profile when user is destroyed, also ":delete" and ":nullify"

One-to-many

class User < ActiveRecord::Base
    has_many :articles           # creates User.articles method
end
-------------------------------
class Article < ActiveRecord::Base
    belongs_to :user             # assumes Article.user_id column
end                              # creates Article.user method

has_many automatic methods

user.articles.size               # array length
user.article_ids                 # list of ids
user.articles << Article.first   # automatically saves association in Article.user_id
user.articles.delete(articles)   # remove articles by setting Article.user_id to null
user.articles.clear              # remove all articles by setting Article.user_id to null
user.articles.find(conditions)   # find a subset of user.articles
user.articles.build(:title => 'Ruby 1.9')   # return associated article but don't save yet
user.articles.create(:title => 'Ruby 1.9')  # return associated article that has already been saved

has_many options

has_many :articles, :class_name => 'Post'          # refer to user.posts instead of user.articles
has_many :articles, :foreign_key => 'post_id'      # refer to user.posts instead of user.articles
has_many :articles, :conditions => "active = 1"    # only consider specific articles
has_many :articles, :order => "published_at DESC"  # default order of user.articles
has_many :articles, :dependent => :destroy         # destroy article when user is destroyed, also ":delete" and ":nullify"


Work with Model Objects

Create and Save

article = Article.new  # make an empty object
article.title = "My Title"  # add attributes
article.author = "Herman"
article.save  # save to database
article.create(:title => "My Title", :author => "Herman")  # make, set attributes, and save
article.new_record?  # new means not saved to database

Find

Article.find(3)                # look for id = 3
Article.first                  # same as Article.find(:first), uses "LIMIT 1" in SQL, so may not be id = 1
Article.last                   # same as Article.find(:last)
Article.all                    # same as Article.find(:all)
Article.where(:title => 'RailsConf').first  # chaining
Article.find_by_title('RailsConf')  # dynamic finder

Update

article = Article.first
article.title = "Rails 3 is great"
article.published_at = Time.now
article.save
article = Article.first
article.update_attributes(:title => "RailsConf2010", :published_at => 1.day.ago)  # saves too

Delete

Article.find(3).destroy  # find, then destroy
Article.destroy(3)       # same thing
Article.delete(3)        # delete directly from database with no object callbacks
Article.delete_all("published_at < '2011-01-01'")  # conditional

Validation and Errors

class Article< ActiveRecord::Base
    validates :title, :presence => true
    validates :body, :presence => true
end
article = Article.new
article.errors.any?           # false
article.save                  # returns false because of validation
article.errors.full_messages  # ["Title can't be blank", "Body can't be blank"]
article.errors.on(:title)     # "can't be blank"
article.valid?                # false