在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在Active Record中,通过在父对象中的has_many来定义到子对象的关联,在子对象中使用belongs_to来指定父对象。我们已经在上一篇中了解了belongs_to声明,实际上,在一对多的情况下,和一对一是相同的,所以我们来了解has_many声明。 has_many声明 has_many声明了一个属性,其行为就像一组子对象,可以把它看作数组来访问,查询特定的对象,或者添加新对象。例如: order = Order.new params[:products_to_buy].each do |prd_id, qty| product = Product.find(prd_id) order.line_items << LineItem.new(:product => product, :quantity => qty) end 追加操作符(>>)所作的不仅仅是向order的line_items列表中追加一个对象,并且和设置了line_item对象外键值为order对象主键值,而且在order对象保存的时候,会同时保存line_item对象。 我们可以像对数组一样对has_many关联进行循环: order = Order.find(123) total = 0.0 order.line_items.each do |li| total += li.quantity * li.unit_price end 和has_one一样,我们可以改变Active Record的默认形式,我们可以给has_many一组设定,:class_name,:foreign_key,:conditions,:order和:dependent和has_one中的是一样的,has_many还有:exclusively_dependent,:finder_sql,:counter_sql。 has_one和has_many都支持:dependent,这告诉Rails在删除主表中记录的同时删除从表中对应的记录。也就是对所有外键为删除的主记录的id的子对象调用它们destory方法。 无论如何,如果从表仅仅和主表关联,而没有其他表关联,而且没有任何钩子方法在删除的时候执行操作,你可以使用:exclusively_dependent来代替:dependent,在这种情况下,对于所有的子记录会使用一条sql语句来删除,这样执行速度会快一点。 你还可以通过使用:finder_sql和:counter_sql设定来复写Active Record用来对子记录进行查询和计数的sql。在:conditions设定不足够的情况下,这两个设定就很有用了。例如: class Order < ActiveRecord::Base has_many :rails_line_items, :class_name => "LineItem", :finder_sql => "select l.* from line_items l, products p " + " where l.product_id = p.id " + " and p.title like '%rails%'" end :counter_sql设定用来复写Active Record用作计算行数的sql,如果:finder_sql被指定了,但是:counter_sql没有指定,Active Record将会根据查询sql来替换计算行数的sql。 :order设定指定了从数据库中选出的记录的排序所使用的sql,如果你在遍历记录集的时候需要有特定的排序,你就需要指定:order,也就是设定sql语句的order by部分,默认情况下,所有的字段都是升序。例如: class Order < ActiveRecord::Base has_many :line_items, :order => "quantity, unit_price DESC" end 现在再回到has_one声明,我们前面提到过也支持:order,但是一条父记录最多只有一条子记录,那么为什么要支持:order来允许指定排序条件呢?想象一下这样的场景,一个用户可能有多条订单,但是,如果我们想查看该用户的最新一条订单呢?这时候,我们就可以使用has_one声明了: class Customer < ActiveRecord::Base has_many :orders has_one :most_recent_order, :class_name => 'Order', :order => 'created_at DESC' end 上面的代码创建了一个新属性:most_recent_order,将会引用到该用户的最新一条订单,我们可以这样使用它: cust = Customer.find_by_name("Dave Thomas") puts "Dave last ordered on #{cust.most_recent_order.created_at}" 实际上,Active Record执行了下面的sql: SELECT * FROM orders WHERE customer_id = ? ORDER BY created_at DESC LIMIT 1 根据前面我们学习的find方法,可以看到只取了排序后的第一条记录。 has_many添加的方法 就像belongs_to和has_one,has_many也添加了一组属性相关的方法在它所在的类中,下面我们来看看这些方法,我们的声明是这样 class Customer < ActiveRecord::Base has_many :orders end l orders(force_reload=false)= 返回一个和用户关联的订单的数组,结果集是被缓存的,对于相同的查询,不会再次从数据库提取数据,除非force_reload = true。 l orders <<order 添加订单到指定用户的订单的列表中。 l orders.push(order1, ...) 添加一个或多个订单对象到用户的订单列表中,concat()是该方法的别名。 l orders.delete(order1, ...) 从用户的订单列表中删除一个或多个订单,但是不会删除数据库中对应的记录,只是将它们的customer_id外键设置为null,断开和用户的关联。 l orders.clear 分离用户和订单,就像delete(),但是如果订单被指明为:dependent,数据库中对应的记录就会被删除。 l orders.find(options...) 发出一个find()调用,但是仅返回用户关联的订单。 l orders.build(attributes={}) 构造一个新的order对象,用给定的属性初始化,并且关联到
2023-10-27 2022-08-15 2022-08-17 2022-09-23 2022-08-13 |
请发表评论