rails笔记 activerecord 关系

actuverecord realation

convention 约定

对应关系:

  • 普通对象: Person -> people table -> person_id
  • join_table: tablenamea_tablenameb 为table名(按照字母顺序排列)

关系

注意belongs_to对应的表必须有外键, rails认为一个表belongs_to他外键引用的表

  • one-to-one

    class Order < ActiveRecord::Base
        has_one :invoices
        . . .
    class Invoice < ActiveRecord::Base
        belongs_to :order
        . . .
    
  • one-to-many: belongs_to

    class Order < ActiveRecord::Base
        has_many :line_items
        . . .
    class LineItem < ActiveRecord::Base
        belongs_to :order 
        . . .
    
  • many-to-many

    class Product < ActiveRecord::Base
        has_and_belongs_to_many :categories
        . . .
    class Category < ActiveRecord::Base
        has_and_belongs_to_many :products
        . . .
    

one-to-one

下面两个操作在逻辑在等价

  • order.invoce=invo
  • auto invo.save

注意1

当把子对象赋给父的时候(order.invoce=invo),子对象如果未存储会自动存储(auto invo.save),但是把父赋给子的时候(invo.order=ord)不会自动存储, 因为此时存储order没有意义, 对应关系是保存在invoces表中的,不过在稍后的invo.save中, 如果父没有创建,还是会自动创建的

注意2 当使用上门的自动存储的时候,由于调用的save方法,所以即使出错也不会报告,所以最好还是自己来invo.save!(比如invo有内部验证的时候),然后在建立连接关系

belongs_to扩展参数,如下例子

class LineItem < ActiveRecord::Base
    belongs_to :paid_order,
        :class_name => "Order",
        :foreign_key => "order_id",
        :conditions => "paid_on is not null"
end
  • :class_name :对应的类
  • :foreign_key :指定外键名
  • :conditions : 用来筛选外键表中的记录(此时foreign_key不能唯一确定记录,或者有不需要的记录)

has_one 也有类似的功能, 多了两个

  • :denpendent

    删除父亲的时候自动删除孤儿(参见hibernate) ???实现失败,加上不加上都不会删除,数据库报外键约束错误

  • :order

    排序,虽然是has_one, 但是这个one可以通过排序动态得到(比如最高分的选手)

hash_one and belongs_to 增加的方法

belongs_to和has_one都会给对象添加下面的方法,假设对应的是product对象

  • product(force_reload=false)

    Return the associated product (or nil if no associated product exists).The result is cached, and the database will not be queried again if this order had previously been fetched unless true is passed as a parameter.

  • product=(obj)

    Associate this line item with the given product, setting the foreign key in this line item to the product’s primary key. If the product has not been saved, it will be when the line item is saved, and the keys will be linked at that time.

  • build_product(attributes={})

    Construct a new product object, initialized using the given attributes.This line item will be linked to it. The product will not yet have been saved.

  • create_product(attributes={})

    Build a new product object, link this line item to it, and save the product.

one-to-many

has_many 扩展声明(未列出的与has_one相同)
  • :dependent

    会把关联他的对象一个一个load出来调用它们的destory

  • :exclusively_dependent

    一个sql删除:denpent需要删除的对象,但是需要保证这些对象真是孤儿而且没有callback

  • :finder_sql

    构建动态的子对象群

  • :counter_sql

    finder_sql调用前call他得到数量, 如果不给出,会自动通过finder_sql添加"count(*)"来计算

  • :order

    排序

has_many 增加的方法
  • orders(force_reload=false)

    Returns an array of orders associated with this customer (which may be empty if there are none). The result is cached, and the database will not be queried again if orders had previously been fetched unless true is passed as a parameter.

  • orders <

    Adds order to the list of orders associated with this customer.orders.push(order1, ...) Adds one or more order objects to the list of orders associated with this customer. concat( ) is an alias for this method.

  • orders.delete(order1, ...)

    Deletes one or more order objects from the list of orders associated with this customer. This does not delete the order objects from the database—it simply sets their customer_id foreign keys to null, breaking their association.

  • orders.clear

    Disassociates all orders from this customer. Like delete( ), this breaks the association but deletes the orders from the database only if they were marked as :dependent.

  • orders.find(options...)

    Issues a regular find( ) call, but the results are constrained only to return orders associated with this customer. Works with the id, the :all, and the :first forms.

  • orders.build(attributes={})

    Constructs a new order object, initialized using the given attributes and linked to the customer. It is not saved.

  • orders.create(attributes={})

    Constructs and save a new order object, initialized using the given attributes and linked to the customer.

many-to-many

在many-to-many中,必须有一个jiontable, 用来保存对应关系,表名的规则是按照字母顺序连接,如 table categories_products join table不能有id ,一方面不需要, 另外一方面会在自动include中覆盖父对象的id

join table额外保存的属性,按道理不应该额外保存属性,额外的属性越明显,就越说明此处的many-to-many关系设计得有问题,适当时候要抽象出一个新model来分别belongs_to两个父亲

relation 中的延迟读取

默认relation关系中都是延迟读取的,如果需要一次性遍历多个记录操作, 可以采用:include指令,下面例子中,include读取三个表只需要一个sql语句(采用left join,需要数据库支持) for post in Post.find(:all, :include => [:author, :comments]) puts "Post: #{post.title}" puts "Written by: #{post.author.name}" puts "Last comment on: #{post.comments.first.created_on}" end

同时要注意,有:include和:condition一起的时候,字段名要全名,如下 ost.find(:all, :conditions => "posts.title like '%ruby%'", :include => [:author, :comments]) # ...

counter_cache

belongs_to :xxx,:counter_cache=>true ,同时父对象表中需要如下的新字段 line_items_count int default 0,注意默认值必须为0(或者其他机制保证初始化为0),否则每次都是null 可以避免每次count都去数据库count(*),这里的cache会在数据增删的时候自动维护

注意 以上的自动更新时, 直接给儿子们更新父亲时是不起作用的, 必须使用father.children(:refresh)才能更新但是使用father.children<< child就没有问题 ???

转载于:https://www.cnblogs.com/baoz/archive/2006/01/24/2269869.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值