|
1. model validates
Rails的model提供了多种validate方法。 比如:
validates_acceptance_of :terms_of_service # 对于checkbox的印证,再合适不过了。
validate_confirmation_of #password confirmation
validates_associated #对assocation的validates。
在save过程中,model的validates先于before_save, before_create这些callback被调用。
我们还可以定置自己的validate方法:
validates_positive_or_zero :number #在lib/validations.rb里面加上这个方法即可。
或者 validates :your_method #在这个methods里面加上印证,如果失败,往erros里面添加错误信息。
2. ActiveRecord的callbacks
要注意各个callback的正确使用,比如: 不要指望after_create保存在对象上所做的改变,除非你显式调用save。因为after_create的调用是在base.save之后。
after_initialize, after_find
http://guides.rubyonrails.org/activerecord_validations_callbacks.html#after-initialize-and-after-find
This behaviour is due to performance reasons, since after_initialize and after_find will both be called for each record found in the database, significantly slowing down the queries.
save & validation
Rails ActiveRecord callback sequence validation callback is before save callback
3. Association
has_many和has_one的validate默认值不同。
比如有两个对象之间的关联是这样的:
class Company has_many :people has_one :addressend
当我们在controller里面这样创建它们时:
def create @person = Person.new(params[:person]) @company = Company.new(params[:person][:company]) @address = Address.new(params[:person][:company][:address]) @company.people << @person @company.address = @address @company.save! end
不要以为address会被验证,其实对于has_one关联,默认的validate为false。
所以,我们要显示得指定:
has_one :address, :validate => true
注意has_one 和 belongs_to的外键所在:
has_one关联,对应的外键在对方表中; belongs_to关联,外键在自身表中。
4. Attributes
attributes_protected attributes_accessible
如果你想让某些值可以被mass assign,比如这样person =Person.new(params[:person]),那么你得把它们声明在attributes_accessible里。当然,你也可以不声明任何的attributes,不过这样会给你带来可能的安全问题。
显而易见,如果只有少部分attributes不允许被mass assign,那么把这些放在attributes_protected里更加方便。
ActiveRecord::Base中的inspect方法
看源码
# File vendor/rails/activerecord/lib/active_record/base.rb, line 2850def inspect attributes_as_nice_string = self.class.column_names.collect { |name| if has_attribute?(name) || new_record? "#{name}: #{attribute_for_inspect(name)}" end }.compact.join(", ") "#<#{self.class} #{attributes_as_nice_string}>"en
明白了么,如果是不在数据库中的attribute,它是不会打出来给你看的~~~
Boolean column:
Rails does a nifty thing with boolean columns: it supports the Rubyquestion mark convention for object attributes that return a booleanRuby value.
Type attribute:
为什么不能用self.type?因为type是ruby的保留方法,它会返回类型信息。所以,要取得对象内的type attribute,就得用self[:type]。可以看出,所有的attributes,都可以用hash的方式取出。
5. Find方法中的select option
有时候为了执行效率,我们会指定select的字段。对于纯粹的数据读取,这没问题。但如果还会对读取之后的数据进行更新,则需要注意,不要在select中落下id字段。
比如:
person = Person.find(:first, :select => "first_name, last_name")person.update_attribute :first_name, person.first_name.downcase
你会发现第二个语句的执行sql是:
update people set first_name = 'bo' where id = nil
这会导致对person的更新不能成功。
正确的操作是:
person = Person.find(:first, :select => "id, first_name, last_name")person.update_attribute :first_name, person.first_name.downcase
则更新操作就会成功:
update people set first_name = 'bo' where id = 12
6. save(false), save and save!
save(false): skip model validation
save: donot skip model validation
save!: raise exception if not valid, create! called it
7. new_record?
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet. def new_record? defined?(@new_record) && @new_record end
8. destory, delete
destory: Deletes the record in the database and freezes this instance to reflectthat no changes should be made. And particularly, it can set callbacks through before_destroy and after_destroy.
delete: it simply delete the row in database and freeze theinstance. But it does not have any callbacks unless you make it byobservers. If you do want callbacks, use destroy.
对于依赖删除的model,如果只是想让关联失效,而不是删除记录,可以使用:nilfy指定。
9. 乐观锁,悲观锁机制
http://guides.rubyonrails.org/active_record_querying.html#locking-records-for-update
10. Eager loading and N +1
clients = Client.all(:limit => 10) clients.each do |client| puts client.address.postcode end 11 queries
VS
clients = Client.all(:include => :address, :limit => 10) clients.each do |client| puts client.address.postcode end
2 queries:
SELECT * FROM clients SELECT addresses.* FROM addresses WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
11. named_scope
定制一个具名的find方法:http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html#M002177
12. accepts_nested_attributes_for
Make complex form easier. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#M002132
|
|