六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 136|回复: 0

Rails每周闲碎(二): Model

[复制链接]

升级  9.67%

67

主题

67

主题

67

主题

举人

Rank: 3Rank: 3

积分
229
 楼主| 发表于 2013-2-7 20:24:03 | 显示全部楼层 |阅读模式
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
 
 
 
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表