1.在我們的模型中添加下面方法
class Article < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :body
def long_title
"#{title} - #{published_at}"
end
end
我們就使用上面的方法來(lái)操作數(shù)據(jù)庫(kù)了
#在命令行中操作模型
>> Article.create :title => 'Advanced Active Record', :published_at => Date.today,
:body => 'Models need to relate to each other. In the real world, ...'
=> #<Article id: 6, title: "Advanced Active Record", ...>
>> Article.last.long_title
=> "Advanced Active Record - 2013-04-22 04:00:00 UTC"
2.數(shù)據(jù)庫(kù)之間的關(guān)系
①一對(duì)一關(guān)系
首先:我們創(chuàng)建兩張表
rails generate model User email:string password:string
rails generate model Profile user_id:integer name:string birthday:date bio:text color:string twitter:string
我們分別在兩個(gè)模型中創(chuàng)建對(duì)應(yīng)的方法
#User模型
class User < ActiveRecord::Base
has_one :profile
end
#Profile模型
class Profile < ActiveRecord::Base
belongs_to :user
end
我們接下來(lái)可以在rails命令行中做測(cè)試了
>> user = User.create(:email => 'user@example.com', :password => 'secret')
=> #<User id: 1, email: "user@example.com", password: "secret",
created_at: "2013-04-02 15:10:07", updated_at: "2013-04-02 15:10:07">
>> profile = Profile.create(:name => 'John Doe',
:bio => 'Ruby developer trying to learn Rails')
=> #<Profile id: 1, user_id: nil, name: "John Doe", birthday: nil,
bio: "Ruby developer trying to learn Rails", color: nil, twitter: nil,
created_at: "2013-04-02 15:10:55", updated_at: "2013-04-02 15:10:55">
>> user.profile
=> nil
>> user.profile = profile
=> #<Profile id: 1, user_id: 1, name: "John Doe", birthday: nil,
bio: "Ruby developer trying to learn Rails", color: nil, twitter: nil,
created_at: "2013-04-02 15:10:55", updated_at: "2013-04-02 15:10:55">
>> user.profile
=> #<Profile id: 1, user_id: 1, name: "John Doe", birthday: nil,
bio: "Ruby developer trying to learn Rails", color: nil, twitter: nil,
created_at: "2013-04-02 15:10:55", updated_at: "2013-04-02 15:10:55">
>> user.create_profile :name => 'Jane Doe', :color => 'pink'
=> #<Profile id: 2, user_id: 1, name: "Jane Doe", birthday: nil,
bio: nil, color: "pink", twitter: nil, created_at: "2013-04-02 15:18:57",
updated_at: "2013-04-02 15:18:57">
一對(duì)一模型中常用方法總結(jié)如下:
user.profile
返回user對(duì)應(yīng)的profile對(duì)象
user.profile=(profile)
對(duì)user的profile賦值
user.profile.nil?
返回user的profile是否為空,為空返回真
user.build_profile(attributes={})
返回一條新的user的profile對(duì)象,但是不會(huì)保存到數(shù)據(jù)庫(kù)老客,需要使用user.profile.save
來(lái)保存
user.create_profile(attributes={})
返回user的profile對(duì)象逢唤,直接保存到數(shù)據(jù)庫(kù)中
②一對(duì)多關(guān)系
我們使用user表對(duì)應(yīng)article表治笨,每個(gè)用戶(hù)都有很多的文章到千,但是每篇文章都只對(duì)應(yīng)一個(gè)用戶(hù)
rails generate migration add_user_id_to_articles user_id:integer
#文章表模型
class Article < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :body
belongs_to :user#每篇文章指定屬于用戶(hù)
def long_title
"#{title} - #{published_at}"
end
end
#用戶(hù)表
class User < ActiveRecord::Base
has_one :profile
has_many :articles
end
我們?cè)趓ails命令 行中使用示例
>> user = User.first
=> #<User id: 1, email: "user@example.com", password: "secret",
created_at: "2013-04-02 15:10:07", updated_at: "2013-04-02 15:10:07">
>> user.articles
=> []
>> user.articles << Article.first
=> [#<Article id: 6, ..., user_id: 1>]
>> user.articles.size
=> 1
>> user.articles
=> [#<Article id: 6, ..., user_id: 1>]
>> Article.first.user_id
=> 1
>> Article.first.user
=> #<User id: 1, email: "user@example.com", password: "secret",
created_at: "2013-04-02 15:10:07", updated_at: "2013-04-02 15:10:07">
一對(duì)多常用方法
user.articles
返回用戶(hù)模型中所有文章對(duì)象
user.articles=(articles)
替換用戶(hù)模型的所有文章對(duì)象昆码,用articles來(lái)代替
user.articles << article
添加article對(duì)象到user的文章對(duì)象中
user.articles.delete(articles)
刪除文章模型中的一篇或者多篇文章
user.articles.empty?
判斷用戶(hù)實(shí)例的文章是否是空的
user.articles.size
返回用戶(hù)示例的文章數(shù)量
user.article_ids
返回用戶(hù)示例的文章id憨琳,以數(shù)組形式返回
user.articles.clear
清空用戶(hù)的文章
user.articles.find
傳入文章的id物咳,返回該文章
user.articles.build(attributes={})
創(chuàng)建一個(gè)新的用戶(hù)文章對(duì)象锣险,不會(huì)保存,需要使用user.articles.last.save
來(lái)保存
user.articles.create(attributes={})
直接創(chuàng)建文章對(duì)象览闰,并且保存到數(shù)據(jù)庫(kù)中芯肤。
③關(guān)系型數(shù)據(jù)庫(kù)擴(kuò)展
i.定義默認(rèn)排序
#指定單個(gè)的排序
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC') }
end
#指定多個(gè)字段排序
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}
end
ii.特殊依賴(lài)
當(dāng)我們刪除一個(gè)用戶(hù)時(shí),該用戶(hù)的所有文章都會(huì)被刪除
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}, :dependent => :destroy
end
當(dāng)然我們也可以不刪除文章压鉴,可以設(shè)置被刪除用戶(hù)的所有文章的user_id為空
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}, :dependent => :nullify
end
④多對(duì)多關(guān)系
我們假定一篇文章有很多種分類(lèi)崖咨,一個(gè)分類(lèi)也有很多文章,我們使用rails generate model Category name:string
和rails generate migration create_articles_categories
分別創(chuàng)建分類(lèi)表和中間表油吭,中間表的定義如下
#The db/migrate/20130407002156_create_articles_categories.rb: File
class CreateArticlesCategories < ActiveRecord::Migration
def change
create_table :articles_categories, :id => false do |t|
t.references :article
t.references :category
end
end
def self.down
drop_table :articles_categories
end
end
references
方法和integer
是一樣的效果击蹲,也就是說(shuō)我們可以使用下面的方式來(lái)創(chuàng)建add_column :articles_categories, :article_id, :integer
,add_column :articles_categories, :category_id, :integer
下面我們分別為Article模型和Category模型添加has_and_belongs_to_many方法
class Article < ActiveRecord::Base
has_and_belongs_to_many :categories
end
class Category < ActiveRecord::Base
has_and_belongs_to_many :articles
end
下面我們?cè)趓ails命令行中測(cè)試,
>> article = Article.last
=> #<Article id: 8, title: "Associations", ...>
>> category = Category.find_by_name('Programming')
=> #<Category id: 1, name: "Programming", ..>
>> article.categories << category
=> [#<Category id: 1, name: "Programming", ..>]
>> article.categories.any?
=> true
>> article.categories.size
=> 1
>> category.articles.empty?
=> false
>> category.articles.size
=> 1
>> category.articles.first.title
=> "Associations"
多對(duì)多關(guān)系需要注意婉宰,我們可以為每個(gè)字段添加索引歌豺,并且可以通過(guò)數(shù)據(jù)庫(kù)來(lái)保證每個(gè)字段的唯一性
add_index :articles_categories, :article_id
add_index :articles_categories, :category_id
add_index :articles_categories, [:article_id, :category_id], unique: true
自定義方法來(lái)模擬多對(duì)多關(guān)系
還是通過(guò)文章和分類(lèi)模型來(lái)定義多對(duì)多關(guān)系
1.創(chuàng)建ac數(shù)據(jù)庫(kù)
class CreateAcs < ActiveRecord::Migration
def change
create_table :acs do |t|
t.integer :article_id
t.integer :category_id
t.timestamps
end
end
end
2.分別在文章和分類(lèi)模型中定義下面的方法
class Article < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :body
belongs_to :user
has_many :acs, dependent: :destroy #這里我們不需要制定外鍵,默認(rèn)是article_id
def long_title
"#{title} -- #{published_at}"
end
def allc
categories = []
self.acs.each {|i| categories << Category.find(i.category_id)}
return categories
end
end
class Category < ActiveRecord::Base
has_many :acs, dependent: :destroy#這里我們不需要制定外鍵芍阎,默認(rèn)是category_id
def alla
articles = []
self.acs.each {|i| articles << Article.find(i.article_id)}
return articles
end
end
最后在ac類(lèi)中定義下面的方法
class Ac < ActiveRecord::Base
belongs_to :article, class_name: "Article"
belongs_to :category, class_name: "Category"
end
這樣我們就可以模擬多對(duì)多關(guān)系了世曾,應(yīng)該比默認(rèn)的方法查詢(xún)速度要快很多吧!