编写测试的指导方针
与应用代码相比,如果测试代码特别简短,倾向于先编写测试;
如果对想实现的功能不是特别清楚,倾向于先编写应用代码,然后再编写测试,并改进实现方式;
安全是头等大事,保险起见,要为安全相关的功能线编写测试;
只要发现一个问题,就编写一个测试重现这种问题,避免回归,然后再编写应用代码修正问题;
尽量不为以后可能修改的代码(例如HTML结构的细节)编写测试;
重构之前要编写测试,集中测试容易出错的代码.
在实际的开发中,根据上述方针,我们一般先编写控制器和模型测试,然后再编写集成测试(测试模型、试视图和控制器在一起时的表现)。如果应用代码很容易出错,或者经常变动(视图就是这样),我们就完全不测试。
assert_select
test中的辅助函数,用于检测html中是否有指定的html标签,这个方法有时也叫”选择符”
assert_select ‘title’,’Home I Ruby on Rails Tutorial Sample App’ #含义: 检测有没有< title >标签,以及其中的内容是不是 “Home I Ruby on Rails Tutorial Sample App”
一些用法:
| 代码 | 匹配HTML |
| ————- |:————-:|
| assert_select ‘div’ | < div>foobar< /div> |
| assert_select ‘div’,’foobar’ | < div>foorbar< /div> |
| assert_select ‘div.nav’ | < div class=’nav’>foorbar< /div> |
| assert_select ‘div#profile’ | < div id=’profile’>foorbar< /div> |
| assert_select ‘div[name=yo]’ | < div name=’yo’>hey< /div> |
| assert_select “a[href=?]”,’/‘,count:1 | < div href=’/‘>foo< /div> |
| assert_select “a[href=?]”,’/‘,text: “foo” | < div href=’/‘>foo< /div> |
选择这样一个input标签的assert_select写法为:
< input id=”email” name=”email” type=”hidden” value=”a@mail.com“ / >
assert_select “input[name=email][type=hidden][value=?]”, ‘a@mail.com‘
provide 帮助方法
1 | <% provide(:title, "Home") %> |
使用git开发的步骤
有新的需求时,创建一个分支,再分支上进行开发,开发完成后合并到主分支.
1 | git checkout master #切换到master分支 |
ps 命令
1 | ps aux #查看系统进程 |
Guard的配置
1 | # Defines the matching rules for Guard. |
bang方法约定
方法名后加一个感叹号的方法称为”炸弹”(bang)方法.bang方法的含义是 方法处理的结果会改变对象的值.比如:
1 | 2.3.1 :001 > a = %w(2 3 5) |
数组的 push | <<
为数组添加元素可以使用 push方法,也可以使用 << 运算符.
1 | 2.3.1 :008 > a << 'bbb' << 'dddd' |
map块变量调用方法简写形式 &
1 | |item| item.upcase } a.map { |
hash
1 | #几种写法 及 多层嵌套后的hash取值方式 |
字符串、数组、hash、Range的声明
1 | a = '' |
预处理引擎的执行顺序
从右向左执行
foobar.js.erb.coffee #先通过coffee处理,再通过ruby处理
路由的 _path 和 _url
root_path -> ‘/‘
root_url -> ‘http://www.example.com/'
约定 只有重定向使用_url形式,其余都使用_path形式.(因为HTTP标准严格要求重定向的URL必须完整.不过在大多数浏览器中,两种形式都可以正常使用)
测试方法 assert_template
检查路由是否使用正确的视图渲染
get root_path
assert_template ‘static_pages/home’
#请求root路由,看root路由是否使用了static_pages下的home视图渲染.
沙盒模式
rails console –sandbox
在沙盒模式下做的所有修改都不会影响实际数据.
在控制台下可以使用 reload方法重新加载环境
ActiveRecord的一些方法
user.new #在内存中创建对象
user.save #保存到数据库,save方法会返回true和false
以上两步和
user.create #create方法会返回对象的实例
等效.
user.valid? #只检测对象是否有效
user.destroy #create方法的逆操作,也会返回对象的实例.(销毁的对象还在内存中)
user.update_attributes(name: ‘The Dude’, email: ‘dude@abides.org‘) #更新name和email属性,返回ture和false.该方法无法跳过验证
user.update_attribute(:name, ‘El Duderino’) #更新单个属性,该方法可以跳过验证
User.find(params[:id]).destroy #可以再查询到的结果上直接调用destroy方法删除对象,物理删除…
Model的验证
validate :email, format: { with: /
1 | VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i |
正则表达式 /i,/g,/m,/gi,/ig 区别
/i (忽略大小写)
/g (全文查找出现的所有匹配字符)
/m (多行查找)
/gi(全文查找、忽略大小写)
/ig(全文查找、忽略大小写)
产生7位随机的字符
(‘a’..’z’).to_a.shuffle[0..7].join
dup方法复制一个对象
duplicate_user = @user.dup
model的 before_save 方法
1 | class User < ApplicationRecord |
has_secure_password 方法
1 | calss User < ApplicationRecord |
在模型中调用了该方法后,会自动添加以下功能:
在数据库中的password_digest列存储安全的密码哈希值;
获得一对虚拟属性,password和password_confirmation,而且创建用户对象时会执行存在性验证和匹配验证;
获得authenticate方法,如果密码正确,返回对应的用户对象,否则返回false;
这个方法需要表有 password_digest字段.
可以根据环境的不同展示debug信息
1 | <div> |
在指定的环境下执行命令
1 | rails console test #在test环境下启用rails console |
健壮参数
1 | params.require(:user).permit(:name,:email,:password,:password_confirmation) |
model的erros对象
1 | user.errors.full_messages #查看所有错误信息,是一个数组 |
helper的pluralize方法
该方法返回正确的单复数形式
1 | helper.pluralize(1,"error") # 1 error |
redirect_to
redirect_to @user
redirect_to user_url(@user)
以上两种形式的含义相同
||= 或等运算符
a ||= b
相当于 a = a || b
当a为真时返回a的值,当a为假时返回b的值
if(a=b)
1 | a = 1 |
上面的代码意思是当b存在时,把b赋给a,然后打印a,当b不存在时,打印3
activerecord的new_record?方法
User.new.new_record? # true
User.first.new_record? #false
用于检测对象是新创建的还是存在于数据库中.
model的validates允许为空的验证
1 | validates :password, presence: true, length: {minimum: 6}, allow_nil: true |
权限验证使用过滤器实现
1 | class ApplicationController < ApplicationController |
删除用户的链接只有管理员才能看到
1 | <% if current_user.admin? && !current_user?(user) % > |
为了限制只有管理员才能删除用户信息,需要这样做
1 | class UserController < ApplicationController |
在数据保存,创建之前都有相应的过滤器
比如: before_create, before_save 等
send方法
1 | 1,2,3] a = [ |
可见send方法可以在对象上调用以字符串或符号方式传入的参数的方法
flash
falsh[:info] = “111” #用在redirect_to中,数据存在session中
falsh.now[:danger] = “111” #用在render中,数据存在request中
has_many 和 belongs_to
当micropost模型和 user模型进行 belongs_to/has_many关联后会获得这些方法:
micropost.user #返回与微博关联的用户对象
user.microposts #返回用户发布的所有微博
user.microposts.create(arg) #创建一篇user发布的微博
user.microposts.create!(arg) #创建一篇user发布的微博(失败时抛出异常)
user.microposts.build(arg) #返回一个user发布的新微博对象
user.microposts.find_by(id:1) #查找user发布的一篇微博,而且微博的id为1
1 | class Micropost < ApplicationRecord |
scope
1 | class Micropost < ApplicationRecord |
Proc(procedure) 匿名函数
-> 接受一个代码块,返回一个Proc,然后再这个Proc上调用call方法执行其中代码.
1 | 'b' } a = -> { puts |
render传递参数
1 | <%= for_for(@micropost) do |f| % > |