美文网首页
读高见龙的《为你自己学Ruby on Rails》后半部分提取笔

读高见龙的《为你自己学Ruby on Rails》后半部分提取笔

作者: 黄鸿亮 | 来源:发表于2018-04-21 19:59 被阅读0次

Model 基本操作

  1. 当我们需要引用外部数据库时,假如我们想改名字,可以这样做:

      class User < ActiveRecord::Base
        self.table_name = "example"
      end
    
  2. 什么是主键(primary key):每個資料表的流水編號欄位(ID).

    当然这个主键也可以自定义

    • class User < ActiveRecord::Base
        self.primary_key = "user_id"
      end
      
    
    
  3. 什么是ORM?

    我們如果想要存取資料庫裡的內容,以前必需透過資料庫查詢語言(SQL)向資料庫進行查詢,但透過 ORM 的包裝之後,可以讓我們用操作「物件」的方式來操作資料庫。

  4. 平均数求和最大值最小值 直接让数据库来计算!

    $ 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
    
  5. 更新数据的方法有 saveupdateupdate_attributeupdate_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)
    
    
    
  6. 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

  1. 什么是migration: 描述数据表长什么样的档案。

  2. 为什么要这样设计:一切为了方便多人协作!

  3. 刚执行rake db:migrate发现要改一下栏位,怎么办?

    • 可以用rollback : rake db:rollback (这样一次可以退回一个migration文件。)
    • 新增migration文件来修改。(推荐!)
  4. 新增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
    
  5. rake db:setup可以一口氣把資料表建完,順便把預設資料寫入。

model的关联性

  1. 什么是外部键:用于对应其他model主键的栏位,例如:user_id product_id

  2. 可以用user.create_post(:title => "hello")来新建对应的资料,生成的资料自动对应好user_id。

  3. 之前商店大赛加油站,无法先新建address再对应user_id,现在终于找到原因和解决方法!:

    • 原因:rails5之后,必须先建立<u></u>才能建立

    • 解法:加多一个optional: true

        class Store < ApplicationRecord
          belongs_to :user, optional: true
        end
      
  4. has_one 跟 belongs_to 方法需要同時設定嗎?

    不一定,端看需求,一樣以我們上面 User 跟 Store 的例子來看,如果你不需要「從 Store 反查 User」的功能的話,那 belongs_to 是不需要設定的。

  5. 其实多对多没有我们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

    有点让新手摸不着头脑。。。

  6. 酷!还有一种叫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 驗證及回呼

  1. 资料验证:有三个方法:

    • 前端驗證:在 HTML 頁面使用 JavaScript 在使用者填寫資料的時候就先檢查。
    • 後端驗證:資料傳進來在寫入資料庫之前之後再檢查。
    • 資料庫驗證:直接由資料庫本身所提供的功能來做資料驗證。

    推荐model层来做这件事!

  2. 验证是否为空:

    • class Article < ApplicationRecord
        validates :title, presence: true
      end
      
    - ```
        class Article < ActiveRecord::Base
          validates_presence_of :title
        end
    

    这两种效果是一样的。

  3. 想查看错误的提示信息?

    • 检查是否有错误提示:a1.errors.any?
    • 检查错误提示是什么:a1.errors.full_messages
  4. 只有这些方法会触发验证:

    • create
    • create!
    • save
    • save!
    • update
    • update!

    其它方法不會經過驗證流程喔

    有驚嘆號版本的,如果驗證未通過會產生錯誤訊息,而沒有驚嘆號版本則僅會回傳該 Model 的一個空物件。这大概就是惊叹号的好处了!

  5. 如何跳过验证?

      user1 = User.new
      user1.save(validate: false)
    
  6. 检查是否能通过验证?

    >> user1.valid?
    => false
    
  7. 回呼(Callback):

    image
  8. 然后,开始$ rspec bank_account_spec.rb进行测试,自然会出错。

  9. 根据错误提示,把所有bug都解掉!

  10. 一些小技巧:

    • before(:each)
    • before(:all)
    • let(:account){BankAccount.new(10)}这个语句相当于动态地为整个方法提供一个区块变数。
  11. 寫測試是算是業界很常見的標準技能,所以:写吧!

代码重构:

  1. 页面上的逻辑可以这样处理:
    • 写进viewhelper
    • 在model里写义一个实体方法,然后在页面就只可以直接用啦!
  2. 善用继承,不能继承的就引入模组功能。

代码重构(进阶版):

  1. 設計 Service Object 類別,新增纯ruby的类别。
  2. 使用 Form Object

表示暂时看不太懂。。。先放过。。

后面的内容实操一遍,基本没有什么重要的知识了……。。

当然这个课程还有一些不错的内容在更新中……

image

相关文章

网友评论

      本文标题:读高见龙的《为你自己学Ruby on Rails》后半部分提取笔

      本文链接:https://www.haomeiwen.com/subject/cpjflftx.html