1、ApplicationRecord

在Rails4中所有的模型都继承自ActiveRecord::Base,不过在Rails5中新引进了一个叫ApplicationRecord的类,存放在: app/models/application_record.rb中,所有Rails5应用都会有这个类, 它的内容非常简单:

class ApplicationRecord < ActiveRecord::Base  
     self.abstract_class = true
   end

就是一个继承ActiveRecord::Base的抽象类,作用就是为整个应用程序模型提供一个自己的基类

module MyModule
  end
  # Rails4.x中扩展模型的方式
  ActiveRecord::Base.send :include, MyModule
  # Rails5
  class ApplicationRecord < ActiveRecord::Base
    include MyModule
    self.abstract_class = true
  end

2、OR语法支持(查询语句的组合查询),Rails5中提供了对两个AR Relation对象的OR方法:

> Article.where(user_id: 1).or(Article.where(user_id: 2))

=> Article Load (2.5ms)  SELECT `articles`.* FROM `articles` WHERE (`articles`.`user_id` = 1 OR `articles`.`user_id` = 2)

需要注意的是如果你在第一个Relation中是用了:limit distinct offset 这三个方法的话,那么就必须在后面的Relation中也使用相同的方法,否则的话就会报错

> Article.where(user_id: 1).limit(1).or(Article.where(user_id: 2))
#=>ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:limit]

最好是在结尾使用:

Article.where(user_id: 1).or(Article.where(user_id: 2)).limit(1)

3、ActiveRecord::Relation#cache_key

Rails中使用缓存是很常见的行为,通常我们要缓存一组查询出来的记录,需要手动的设置缓存的key

no_nick_name_users = User.where(nick_name: nil)
cache_key = [User.name, 'no_nick_name_users', no_nick_name_users.maximum(:updated_at).to_i]
Rails.cache.fetch(cache_key) do
  no_nick_name_users.to_a
end

Rails5中提供了ActiveRecord::Relation#cache_key

no_nick_name_users = User.where(nick_name: nil)
Rails.cache.fetch(no_nick_name_users.cache_key) do
  no_nick_name_users.to_a
end
puts no_nick_name_users.cache_key
#=> "users/query-dae9b6f1d9babd4a9ec4c532614c29eb-1-20160703095605000000"

上面最后一行,Rails5提供的cache_key和我们自己设置的很相似,分别有5个组成部分分别是:

users : 表名
    query : 常值
    dae9b6f1d9babd4a9ec4c532614c29eb : 缓存SQL的MD5码
    1 : 结果集数量
    20160703095605000000 : 结果集最大的updated_at的时间戳

4、AR Relation调用update会触发callbacks和validates

在Rails4中的AR Relation 提供了两个更新记录的方法update_all和update其中:

update_all 通过一条SQL语句更新多条记录,不能触发callback和validate
    update 通过N条SQL语句,更新N条记录,其中N取决于其第一个ID参数的个数。

通过上面的方法定义,可以看出,如果你不知道ID的情况下,想更新一组记录并且触发它们各自的callback和validate,在Rails4中是做不到的。
那么在Rails5中修改了AR Relation#update的实现:

def update(id = :all, attributes)
   if id.is_a?(Array)
     id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
   elsif id == :all
     to_a.each { |record| record.update(attributes) }
   else
     object = find(id)
     object.update(attributes)
    object
  end
end

也就是亦可以通过下面的方法更新记录:

2.3.0 :007 > User.where(nick_name: 'Falm').update(nick_name: 'falm')
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`nick_name` = 'Falm'
   (0.1ms)  BEGIN
  SQL (0.3ms)  UPDATE `users` SET `nick_name` = 'falm', `updated_at` = '2016-07-03 05:00:18' WHERE `users`.`id` = 1
   (2.0ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.2ms)  UPDATE `users` SET `nick_name` = 'falm', `updated_at` = '2016-07-03 05:00:18' WHERE `users`.`id` = 2
   (0.3ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.2ms)  UPDATE `users` SET `nick_name` = 'falm', `updated_at` = '2016-07-03 05:00:18' WHERE `users`.`id` = 3
   (0.2ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.2ms)  UPDATE `users` SET `nick_name` = 'falm', `updated_at` = '2016-07-03 05:00:18' WHERE `users`.`id` = 4
   (0.2ms)  COMMIT

更新操作被按ID分解成多个update语句,并且其中每一个都会执行callback和validates, 要注意的是如果你要更新的记录不必要触发callback或validates,那么因为性能原因最好使用update_all方法。
更新记录时,不更新updated_at/updated_on

Rails4.x中,更新记录是,AR都会连带更新,记录上的updated_at或updated_on字段。
在Rails5中,为ActiveRecord::Base#save方法提供了一个选项,touch: boolean,默认情况下是true,如果设置成false的话,更新记录是就不会更新updated_at字段了。

2.3.0 :027 > user = User.first
  User Load (0.3ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
 => #<User id: 1, phone: "13303300333", email: nil, sign_in_count: 0, name: "Jason", nick_name: "falm", encrypted_password: nil, created_at: "2016-07-03 05:00:14", updated_at: "2016-07-03 05:00:18">
2.3.0 :028 > user.phone = '15088833388'
 => "15088833388"
2.3.0 :029 > user.save(touch: false)
   (0.2ms)  BEGIN
  SQL (0.3ms)  UPDATE `users` SET `phone` = '15088833388' WHERE `users`.`id` = 1
   (0.4ms)  COMMIT
 => true
2.3.0 :030 > user.updated_at
 => Sun, 03 Jul 2016 05:00:18 UTC +00:00

5、忽略字段

Rails5中新增了 ActiveRecord::Base.ignored_columns 方法,用于忽略数据表中不需要的字段(model中定义忽略的字段)。

class User < ApplicationRecord
  self.ignored_columns = ['sign_in_count']
end

这样在模型中就不会有这个字段了

2.3.0 :033 > User.first
  User Load (0.2ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
 => #<User id: 1, phone: "15088833388", email: nil, name: "Jason", nick_name: "falm", encrypted_password: nil, created_at: "2016-07-03 05:00:14", updated_at: "2016-07-03 05:00:18">

6、Belongs_to关联,默认必填

在Rails5中AR中的belongs_to 关联,默认情况下是不能为空的:

class User < ApplicationRecord
end
class Article < ApplicationRecord  
  belongs_to :user
end
> Article.create(title: 'without user').errors.full_messages.to_sentence
   (0.2ms)  BEGIN
   (0.1ms)  ROLLBACK
 => "User must exist"

Article属于User,但是如果没有在创建时指定user的话,就无法通过AR的validates,如果你想去除这个默认选项的话,可以通过下面的方式:

class Article < ApplicationRecord  
  belongs_to :user, optional: true, #指定可选
end

也可以在application.rb中全局设置这个特性为可选的。

Rails.application.config.active_record.belongs_to_required_by_default = false

7、新的 after_{create,update,delete}_commit 回调

在Rails4中,我们可以在模型中设置事务执行后的回调方法,

# == Schema Information
#
# Table name: users
#
#  id                 :integer          not null, primary key
#  phone              :string(255)      not null
#  email              :string(255)
#  sign_in_count      :integer          default(0)
#  name               :string(255)      not null
#  nick_name          :string(255)
#  encrypted_password :string(255)
#  created_at         :datetime         not null
#  updated_at         :datetime         not null
#
class User < ApplicationRecord
  after_commit :send_message, on: :create
  after_commit :send_message, on: :update
  after_commit :send_message, on: :destroy
  private
  def send_message
    do_someting
  end
end

以上就是分别在 创建,更新,和删除事务执行后,被调用的回调方法
那么在Rails5中给它们分别提供的单独的别名方法:

class User < ApplicationRecord
  after_create_commit :send_message
  after_update_commit :send_message
  after_destroy_commit :send_message
  private
  def send_message
    do_someting
  end
end

8、rails4中执行数据迁移使用rake,rails5中为了不来回切换而统一使用rails即可:

rails 4:rake db:migrate

rails 5:rails db:migrate

9、支持在migration中添加comments

在大多数的项目中,快速变化的业务模型是很常见的事情,随之而来的就是数据模型的频繁变化,在这种场景下,我们通常会使用 migration_comments + annotate_models 这两个gem 去为模型添加注释信息,以便能够更好的解释模型的由来和用途。现在Rails5原生支持了 migration_comments的功能:

#encoding: utf-8
class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users, comment: '用户表' do |t|
      t.string :phone, null: false, comment: '手机号'
      t.string :email, comment: '邮箱'
      t.integer :sign_in_count, default: 0, comment: '登录次数'
      t.string :name, null: false, comment: '用户名'
      t.string :nick_name, comment: '昵称'
      t.string :encrypted_password, comment: '加密密码'
      t.timestamps
    end
  end
end

运行迁移:

$> rails db:migrate
== 20160703025729 CreateUsers: migrating ======================================
-- create_table(:users, {:comment=>"用户表"})
   -> 0.0178s
== 20160703025729 CreateUsers: migrated (0.0179s) =============================

在mysql数据库中也可以查看到注释:

mysql> show full columns from users;
+--------------------+--------------+-----------------+--------+-------+-----------+----------------+---------------------------------+-----------+
| Field              | Type         | Collation       | Null   | Key   |   Default | Extra          | Privileges                      | Comment   |
|--------------------+--------------+-----------------+--------+-------+-----------+----------------+---------------------------------+-----------|
| id                 | int(11)      | <null>          | NO     | PRI   |    <null> | auto_increment | select,insert,update,references |           |
| phone              | varchar(255) | utf8_general_ci | NO     |       |    <null> |                | select,insert,update,references | 手机号    |
| email              | varchar(255) | utf8_general_ci | YES    |       |    <null> |                | select,insert,update,references | 邮箱      |
| sign_in_count      | int(11)      | <null>          | YES    |       |         0 |                | select,insert,update,references | 登录次数  |
| name               | varchar(255) | utf8_general_ci | NO     |       |    <null> |                | select,insert,update,references | 用户名    |
| nick_name          | varchar(255) | utf8_general_ci | YES    |       |    <null> |                | select,insert,update,references | 昵称      |
| encrypted_password | varchar(255) | utf8_general_ci | YES    |       |    <null> |                | select,insert,update,references | 加密密码  |
| created_at         | datetime     | <null>          | NO     |       |    <null> |                | select,insert,update,references |           |
| updated_at         | datetime     | <null>          | NO     |       |    <null> |                | select,insert,update,references |           |
+--------------------+--------------+-----------------+--------+-------+-----------+-----------

rails 5 功能新增及改变的更多相关文章

  1. Java第十二次作业:什么是一维数组?什么是对象数组?吃金币游戏2.0版 新增炸弹功能 新增游戏倒计时功能 新增胜利失败检测功能 使用如鹏游戏引擎制作窗体 一维数组设置金币

    什么是数组? 数组的定义:是用统一的名字代表这批数据,用序号来区分各个数据.数组是无序的数据元素按有序的下标组成的集合,分配固定空间大小的一种容器. 如何理解:其实就是一个同时放很多数据的变量. a= ...

  2. java在线聊天项目0.4版本 制作服务端接收连接,客户端连接功能 新增客户端窗口打开时光标指向下边文本域功能,使用WindowListener监听WindowAdapter

    建一个服务端类ChatServer,用于设置端口接收连接 package com.swift; import java.io.IOException; import java.net.ServerSo ...

  3. RandomAccessFile()实现用户注册功能, 新增,查询,更新

    package seday03.raf;import java.io.IOException;import java.io.RandomAccessFile;import java.util.Arra ...

  4. Windows Server 2016-DNS 新增或改进功能

    本章节补充介绍在 Windows Server 2016 中域名系统 (DNS) 服务器新增或已更改的功能相关信息,具体内容如下: 功能 新增或改进 描述 DNS 策略 新增 您可以配置 DNS 策略 ...

  5. Excelize 2.5.0 正式发布,这些新增功能值得关注

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...

  6. SCVMM之Windows Server2012 R2新功能

    在Windows Server 2012 R2中可以通过使用共享的虚拟硬盘VHDX文件的方法来模拟IP SAN,来为虚拟机创建群集提供共享存储.这样为虚拟机创建群集时就不用再像以前一样通过使用软件模拟 ...

  7. Rails 建立一个资源

    在blog 应用程序中.你可以通过脚手架(scaffolded)开始建立一个资源. 这将是单一的blog 提交.请输入以下命令 $ rails generate scaffold Post name: ...

  8. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  9. iOS 10 都有什么改变?

    iOS 10 都有什么改变? 看这一个贴就够了 最全面的试用 苹果在 WWDC 2016 发布会上正式发布了 iOS 10 操作系统,iOS 与 macOS.tvOS 和 watchOS 构建了苹果四 ...

随机推荐

  1. 程序员修神之路--kubernetes是微服务发展的必然产物

    菜菜哥,我昨天又请假出去面试了 战况如何呀? 多数面试题回答的还行,但是最后让我介绍微服务和kubernetes的时候,挂了 话说微服务和kubernetes内容确实挺多的 那你给我大体介绍一下呗 可 ...

  2. 并行模式之Master-Worker模式

    并行模式之Master-Worker模式 一).Master-Worker模式 作用: 将一个大任务分解成若干个小任务,分发给多个子线程执行. 注: 将大任务分解成小任务,小任务的实现逻辑要相同. 二 ...

  3. 启动elasticsearch

       - name: source env      shell: source /etc/profile    - name: make elastic permission      shell: ...

  4. 串烧 JavaCAS相关知识

    JMM与问题引入 为啥先说JMM,因为CAS的实现类中维护的变量都被volatile修饰, 这个volatile 是遵循JMM规范(不是百分百遵循,下文会说)实现的保证多线程并发访问某个变量实现线程安 ...

  5. C# - SPC(Statistical Process Control)系统 - 6西格玛数据决策和Chart模块的开发与实现

    Statistical Process Control 简介 统计过程控制(Statistical Process Control)是一种借助数理统计方法的过程控制工具.它对生产过程进行分析评价,根据 ...

  6. MySQL常用的查询语句回顾

    让你快速复习语句的笔记宝典. create table users(    username varchar(20) primary key,    userpwd varchar(20) ) alt ...

  7. 使用python脚本执行地理处理工具

    桌面ArcGIS包含800多种可在Python脚本中运行的地理处理工具. 通过Python脚本来运行地理处理工具,可以处理复杂的工作和执行批处理任务. 案例一:使用脚本执行地理处理工具(以裁剪为例) ...

  8. Caffe 图像分类

      本文主要描述如何使用 CAFFE 进行图像分类. 开发环境要求:windows 10 64位.Visual Studio 2017..NET framework 4.6.1     分类 在一个项 ...

  9. 英语口语考试资料Volunteers

    Being a volunteer is great!        There are lots of volunteers around us now. And they don’t do it ...

  10. 大白话OSI七层协议

    目录 一.物理层 二.数据链路层 2.1 以太网协议 2.2 Mac地址 2.3 广播地址 三.网络层 3.1 IP协议详解 3.1.1 IP地址的两部分 3.2 子网掩码详解 3.3 IP数据包详解 ...