1.在我們的模型中添加下面方法
class Article < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :body
def long_title
"#{title} - #{published_at}"
end
end
我們就使用上面的方法來操作數據庫了
#在命令行中操作模型
>> 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.數據庫之間的關系
①一對一關系
首先:我們創建兩張表
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
我們分別在兩個模型中創建對應的方法
#User模型
class User < ActiveRecord::Base
has_one :profile
end
#Profile模型
class Profile < ActiveRecord::Base
belongs_to :user
end
我們接下來可以在rails命令行中做測試了
>> 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">
一對一模型中常用方法總結如下:
user.profile
返回user對應的profile對象
user.profile=(profile)
對user的profile賦值
user.profile.nil?
返回user的profile是否為空,為空返回真
user.build_profile(attributes={})
返回一條新的user的profile對象,但是不會保存到數據庫,需要使用user.profile.save
來保存
user.create_profile(attributes={})
返回user的profile對象,直接保存到數據庫中
②一對多關系
我們使用user表對應article表,每個用戶都有很多的文章,但是每篇文章都只對應一個用戶
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#每篇文章指定屬于用戶
def long_title
"#{title} - #{published_at}"
end
end
#用戶表
class User < ActiveRecord::Base
has_one :profile
has_many :articles
end
我們在rails命令 行中使用示例
>> 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">
一對多常用方法
user.articles
返回用戶模型中所有文章對象
user.articles=(articles)
替換用戶模型的所有文章對象,用articles來代替
user.articles << article
添加article對象到user的文章對象中
user.articles.delete(articles)
刪除文章模型中的一篇或者多篇文章
user.articles.empty?
判斷用戶實例的文章是否是空的
user.articles.size
返回用戶示例的文章數量
user.article_ids
返回用戶示例的文章id,以數組形式返回
user.articles.clear
清空用戶的文章
user.articles.find
傳入文章的id,返回該文章
user.articles.build(attributes={})
創建一個新的用戶文章對象,不會保存,需要使用user.articles.last.save
來保存
user.articles.create(attributes={})
直接創建文章對象,并且保存到數據庫中。
③關系型數據庫擴展
i.定義默認排序
#指定單個的排序
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC') }
end
#指定多個字段排序
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}
end
ii.特殊依賴
當我們刪除一個用戶時,該用戶的所有文章都會被刪除
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}, :dependent => :destroy
end
當然我們也可以不刪除文章,可以設置被刪除用戶的所有文章的user_id為空
class User < ActiveRecord::Base
has_one :profile
has_many :articles, -> { order('published_at DESC, title ASC')}, :dependent => :nullify
end
④多對多關系
我們假定一篇文章有很多種分類,一個分類也有很多文章,我們使用rails generate model Category name:string
和rails generate migration create_articles_categories
分別創建分類表和中間表,中間表的定義如下
#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
是一樣的效果,也就是說我們可以使用下面的方式來創建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
下面我們在rails命令行中測試,
>> 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"
多對多關系需要注意,我們可以為每個字段添加索引,并且可以通過數據庫來保證每個字段的唯一性
add_index :articles_categories, :article_id
add_index :articles_categories, :category_id
add_index :articles_categories, [:article_id, :category_id], unique: true
自定義方法來模擬多對多關系
還是通過文章和分類模型來定義多對多關系
1.創建ac數據庫
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.分別在文章和分類模型中定義下面的方法
class Article < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :body
belongs_to :user
has_many :acs, dependent: :destroy #這里我們不需要制定外鍵,默認是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#這里我們不需要制定外鍵,默認是category_id
def alla
articles = []
self.acs.each {|i| articles << Article.find(i.article_id)}
return articles
end
end
最后在ac類中定義下面的方法
class Ac < ActiveRecord::Base
belongs_to :article, class_name: "Article"
belongs_to :category, class_name: "Category"
end
這樣我們就可以模擬多對多關系了,應該比默認的方法查詢速度要快很多吧!