Model 基本操作
-
当我们需要引用外部数据库时,假如我们想改名字,可以这样做:
class User < ActiveRecord::Base self.table_name = "example" end
-
什么是
主键
(primary key):每個資料表的流水編號欄位(ID).当然这个主键也可以自定义:
class User < ActiveRecord::Base self.primary_key = "user_id" end
-
什么是ORM?
我們如果想要存取資料庫裡的內容,以前必需透過資料庫查詢語言(SQL)向資料庫進行查詢,但透過 ORM 的包裝之後,可以讓我們用操作「物件」的方式來操作資料庫。
-
平均数
,求和
,最大值
,最小值
直接让数据库来计算!$ bin/rails console >> Candidate.sum(:age) (0.2ms) SELECT SUM("candidates"."age") FROM "candidates" => 44 >> Candidate.average(:age).to_f (0.1ms) SELECT AVG("candidates"."age") FROM "candidates" => 14.6666666666667
$ bin/rails console >> Candidate.maximum(:age) (0.2ms) SELECT MAX("candidates"."age") FROM "candidates" => 22 >> Candidate.minimum(:age) (0.2ms) SELECT MIN("candidates"."age") FROM "candidates" => 2
-
更新数据的方法有
save
、update
、update_attribute
及update_attributes
:# 使用 save 方法 candidate.name = "剪彩倫" candidate.save # 使用 update_attribute 方法更新單一欄位的值(注意:方法名字是單數) candidate.update_attribute(:name, "剪彩倫") # 使用 update 更新資料,可一次更新多個欄位,且不需要再呼叫 save 方法 candidate.update(name: "剪彩倫", age: 20) # 使用 update_attributes 方法 candidate.update_attributes(name: "剪彩倫", age: 20)
單數的 `update_attribute` 方法會跳過驗證(Validation),等於是 `save(validate: false)` 的效果,在使用的時候要稍微注意一下。 - 如果想整个资料表一起修改:
Candidate.update_all(name: "剪彩倫", age: 18)
-
scope可以嵌套,利用嵌套,可以方便我们:
- 使代码整洁。
- 方便我们修改。
还可以:预设scope,
class Product < ActiveRecord::Base default_scope { order('id DESC') } scope :available, -> { where(is_available: true) } end
要取消預設的 scope,必須使用
unscope
方法:$ bin/rails console >> Product.unscope(:order) Product Load (0.2ms) SELECT "products".* FROM "products" >> Product.unscope(:order).order(:title) Product Load (0.3ms) SELECT "products".* FROM "products" ORDER BY "products"."title" ASC
這樣才能把預設的 scope 的效果移除。
Model Migration
-
什么是migration: 描述数据表长什么样的档案。
-
为什么要这样设计:一切为了方便多人协作!
-
刚执行
rake db:migrate
发现要改一下栏位,怎么办?- 可以用
rollback
:rake db:rollback
(这样一次可以退回一个migration文件。) - 新增migration文件来修改。(推荐!)
- 可以用
-
新增migration文件时,原来可以直接上index索引啊,酷!:
$ bin/rails g migration add_candidate_id_to_articles candidate_id:integer:index Running via Spring preloader in process 7765 invoke active_record create db/migrate/20170101081538_add_candidate_id_to_articles.rb
class AddCandidateIdToArticles < ActiveRecord::Migration[5.0] def change add_column :articles, :candidate_id, :integer add_index :articles, :candidate_id end end
-
rake db:setup
可以一口氣把資料表建完,順便把預設資料寫入。
model的关联性
-
什么是外部键:用于对应其他model主键的栏位,例如:
user_id
product_id
-
可以用
user.create_post(:title => "hello")
来新建对应的资料,生成的资料自动对应好user_id。 -
之前商店大赛加油站,无法先新建address再对应user_id,现在终于找到原因和解决方法!:
-
原因:rails5之后,必须先建立<u>
头
</u>才能建立尾
! -
解法:加多一个
optional: true
class Store < ApplicationRecord belongs_to :user, optional: true end
-
-
has_one 跟 belongs_to 方法需要同時設定嗎?
不一定,端看需求,一樣以我們上面 User 跟 Store 的例子來看,如果你不需要「從 Store 反查 User」的功能的話,那
belongs_to
是不需要設定的。 -
其实多对多没有我们rails101教材上的那么复杂,其实可以这么简单:
class WareHouse < ApplicationRecord belongs_to :store belongs_to :product end
class Store < ApplicationRecord belongs_to :user has_many :ware_houses has_many :products, through: :ware_houses end
class Product < ApplicationRecord has_many :ware_houses has_many :stores, through: :ware_houses end
看到没有,第二个has_many只要写两个字段就可以啦!之前是这样的:
image
有点让新手摸不着头脑。。。
-
酷!还有一种叫HABTM(has_and_belongs_to_many)!
# Store Model class Store < ActiveRecord::Base has_and_belongs_to_many :products end # Product Model class Product < ActiveRecord::Base has_and_belongs_to_many :stores end
就這樣,不需要另外新增第三方 Model 即可完成多對多關連。注意,我是說「不需要第三方 Model」,不是「不需要第三方資料表」,畢竟還是要有一個資料表存放雙方的資訊,只是這個資料表因為不重要也不會存取它,所以可以不需要 Model 對應。
這個第三方資料表的名字是有規定的,預設是「兩個資料表依照英文字母先後順序排序,中間以底線分格」,所以以我們這個例子來說,這個資料表的名字就是「products_stores」。
Model 驗證及回呼
-
资料验证:有三个方法:
- 前端驗證:在 HTML 頁面使用 JavaScript 在使用者填寫資料的時候就先檢查。
- 後端驗證:資料傳進來在寫入資料庫之前之後再檢查。
- 資料庫驗證:直接由資料庫本身所提供的功能來做資料驗證。
推荐model层来做这件事!
-
验证是否为空:
class Article < ApplicationRecord validates :title, presence: true end
- ``` class Article < ActiveRecord::Base validates_presence_of :title end
这两种效果是一样的。
-
想查看错误的提示信息?
- 检查是否有错误提示:
a1.errors.any?
- 检查错误提示是什么:
a1.errors.full_messages
- 检查是否有错误提示:
-
只有这些方法会触发验证:
- create
- create!
- save
- save!
- update
- update!
其它方法不會經過驗證流程喔
有驚嘆號版本的,如果驗證未通過會產生錯誤訊息,而沒有驚嘆號版本則僅會回傳該 Model 的一個空物件。这大概就是惊叹号的好处了!
-
如何跳过验证?
user1 = User.new user1.save(validate: false)
-
检查是否能通过验证?
>> user1.valid? => false
-
回呼(Callback):
image
-
然后,开始
$ rspec bank_account_spec.rb
进行测试,自然会出错。 -
根据错误提示,把所有bug都解掉!
-
一些小技巧:
- before(:each)
- before(:all)
-
let(:account){BankAccount.new(10)}
这个语句相当于动态地为整个方法提供一个区块变数。
-
寫測試是算是業界很常見的標準技能,所以:写吧!
代码重构:
- 页面上的逻辑可以这样处理:
- 写进viewhelper
- 在model里写义一个实体方法,然后在页面就只可以直接用啦!
- 善用继承,不能继承的就引入模组功能。
代码重构(进阶版):
-
設計 Service Object 類別,新增纯ruby的类别。
-
使用 Form Object
表示暂时看不太懂。。。先放过。。
后面的内容实操一遍,基本没有什么重要的知识了……。。
当然这个课程还有一些不错的内容在更新中……
image
网友评论