Aiur

zellux 的博客

ActiveRecord 的一些细节

Permalink

对象属性

ActiveRecord 对象在数据库中的属性并不是以实体变量的方式保存的,如果要为一个属性设置默认值的话,

1
2
3
4
5
class Item < ActiveRecord::Base
  def category
    @category || 'n/a'
  end
end

这样的实现是不可行的。读取和修改这些属性时应该使用 read_attribute 和 write_attribute:

1
2
3
4
5
class Item < ActiveRecord::Base
  def category
    read_attribute(:category) || 'n/a'
  end
end

Hash 和相等性

ActiveRecord 的 hash 值是根据主键的值计算出来的,这就意味着未保存对象的 hash 值是不可靠的。同样两个 model 对象的相等比较(即==操作符)也是基于主键的,所以两个 model 对象即使它们的其他属性不一样,仍有可能被当作相等。

查找

find_by_attribute 方法后面加个 ! 号,即使用 find_by_attribute!,就能在找不到对象的时候触发一个 RecordNotFound 异常,而不是返回 nil。

find_or_initialize_by 和 find_or_create_by 也是两个好用的方法,它们在找不到对象时分别使用 new 和 create 新建一个,并用查找的属性初始化新建的对象。

手写 SQL

不得不手写 SQL 同时又要防止注入攻击的一个比较简洁的写法是

1
    Order.where("name = :name and pay_type = :pay_type", params[:order])

回调函数

出于性能考虑,after_find 和 after_initialize 只能通过函数声明的方式定义,即不能用类似 before_validation :normalize_fields 这样的形式。

参考

评论