Ruby on Rails中的ActiveRecord编程指南
避免改动缺省的ActiveRecord(表的名字、主键,等等),除非你有一个非常好的理由(像是不受你控制的数据库)。
把宏风格的方法放在类别定义的前面(has_many,validates,等等)。
偏好has_many:through胜于has_and_belongs_to_many。使用has_many:through允许在join模型有附加的属性及验证
#使用has_and_belongs_to_many classUser<ActiveRecord::Base has_and_belongs_to_many:groups end classGroup<ActiveRecord::Base has_and_belongs_to_many:users end #偏好方式-usinghas_many:through classUser<ActiveRecord::Base has_many:memberships has_many:groups,through::memberships end classMembership<ActiveRecord::Base belongs_to:user belongs_to:group end classGroup<ActiveRecord::Base has_many:memberships has_many:users,through::memberships end
使用新的"sexy"validation。
当一个惯用的验证使用超过一次或验证是某个正则表达映射时,创建一个惯用的validator文件。
#差 classPerson validates:email,format:{with:/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i} end #好 classEmailValidator<ActiveModel::EachValidator defvalidate_each(record,attribute,value) record.errors[attribute]<<(options[:message]||'isnotavalidemail')unlessvalue=~/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i end end classPerson validates:email,email:true end
所有惯用的验证器应放在一个共享的gem。
自由地使用命名的作用域(scope)。
classUser<ActiveRecord::Base scope:active,->{where(active:true)} scope:inactive,->{where(active:false)} scope:with_orders,->{joins(:orders).select('distinct(users.id)')} end
将命名的作用域包在lambda里来惰性地初始化。
#差劲 classUser<ActiveRecord::Base scope:active,where(active:true) scope:inactive,where(active:false) scope:with_orders,joins(:orders).select('distinct(users.id)') end #好 classUser<ActiveRecord::Base scope:active,->{where(active:true)} scope:inactive,->{where(active:false)} scope:with_orders,->{joins(:orders).select('distinct(users.id)')} end
当一个由lambda及参数定义的作用域变得过于复杂时,更好的方式是建一个作为同样用途的类别方法,并返回一个ActiveRecord::Relation对象。你也可以这么定义出更精简的作用域。
classUser<ActiveRecord::Base defself.with_orders joins(:orders).select('distinct(users.id)') end end
注意update_attribute方法的行为。它不运行模型验证(不同于update_attributes)并且可能把模型状态给搞砸。
使用用户友好的网址。在网址显示具描述性的模型属性,而不只是id。
有不止一种方法可以达成:
覆写模型的to_param方法。这是Rails用来给对象建构网址的方法。缺省的实作会以字串形式返回该id的记录。它可被另一个具人类可读的属性覆写。
classPerson defto_param "#{id}#{name}".parameterize end end
为了要转换成对网址友好(URL-friendly)的数值,字串应当调用parameterize。对象的id要放在开头,以便给ActiveRecord的find方法查找。
*使用此friendly_idgem。它允许藉由某些具描述性的模型属性,而不是用id来创建人类可读的网址。
Ruby classPerson extendFriendlyId friendly_id:name,use::slugged end
查看gem文档获得更多关于使用的信息。