首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Rails 3.1中显示父行的第一个和最后一个子记录?

如何在Rails 3.1中显示父行的第一个和最后一个子记录?
EN

Stack Overflow用户
提问于 2012-01-02 23:21:17
回答 2查看 499关注 0票数 1

我对Rails相当陌生,我很喜欢Rails的表达式建模体系结构。我目前正在构建一个路由系统,在两个表之间有一个到多个链接。

考虑以下模式:

代码语言:javascript
复制
class CreateTrips < ActiveRecord::Migration
  def self.up
    create_table :trips do |t|
      t.string :name
    end
  end
  ...
end


class CreatePitStop < ActiveRecord::Migration
  def self.up
    create_table :pit_stops do |t|
      t.references :trip
      t.integer :stop_number
      t.string :location
    end
  end
  ...
end

现在考虑一下一次旅行的下列数据:

代码语言:javascript
复制
t = Trips.create!({ :name => "Christmas Visits Route" })
t.pit_stops.create!({ :stop_number => 1, :location => "Home" })
t.pit_stops.create!({ :stop_number => 2, :location => "Mom and Dads" })
t.pit_stops.create!({ :stop_number => 3, :location => "In-Laws" })
t.pit_stops.create!({ :stop_number => 4, :location => "Grandma's" })
t.pit_stops.create!({ :stop_number => 5, :location => "Time Square" })

我想要做的是为'trips/index‘视图在一个单独的" trip“行中显示所有trip名称的列表以及第一个和最后一个PitStop的位置。我不在乎中间站的位置,我只想知道我从哪里开始,在哪里结束:

代码语言:javascript
复制
--------
My Trips
--------

--------------------------------------------------------
| Route Name              | From   | To                |
--------------------------------------------------------
| Christmas Visits Route  | Home   | Time Square       |
--------------------------------------------------------

我想从查询中删除所有的“中间”PitStops,因为每次旅行都会有很多。

问题:使用ActiveRecord从数据库中提取数据的最佳方法是什么?

解决方案:2012年1月3日

我通过将PitStop逻辑应用到Trip模型中来解决我的问题。我的From和To PitStops现在有了硬编码的stop_number值。在研究了它之后,我发现这个解决方案对于现实世界也是有意义的(双赢)。

  • PitStop记录的stop_number值总是为0。
  • To PitStop记录的stop_number值始终为99.

F 214

这是有意义的,因为第一个PitStop根本不是真正的“停站”,它是你从哪里开始的。0)。最后一个PitStop也不是真正的“停站”,它是你的终点站。99)。当然,这假设任何路线都不会有超过98个“停站”。)对我来说安全的假设.

这些逻辑定义的"stop_numbers“还解决了我查询所有子PitStops以查找'trips/index‘显示的问题,并且我可以在每次旅行中快速有效地查询这些值(不再对.first.last进行子查询):

代码语言:javascript
复制
class Trip
  has_many :pit_stops
  has_one :starting_from, :class => 'PitStop', 
          :conditions => 'pit_stops.stop_number == 0'
  has_one :ending_at, :class => 'PitStop', 
          :conditions => 'pit_stops.stop_number == 99'

  def add_pit_stop(location)
    stop_num = @pit_stops.count - 1 # accounts for stop_number 99
    @pit_stops.create!({ :stop_number => stop_num, 
                         :location => location})
  end
end

正如您所看到的,在定义starting_fromending_at记录(现在是逻辑业务规则)之后,输入stop_numbers的诀窍现在是一个简单的数学公式。现在我可以简单地说:

代码语言:javascript
复制
trip = create_trip("Christmas Visits", "Home", "Time Square")
trip.add_pit_stop("Mom and Dads")
trip.add_pit_stop("In-Laws")
trip.add_pit_stop("Grandma's")

我的(已订购的) PitStop记录现在如下所示:

代码语言:javascript
复制
{ :stop_number => 0, :location => "Home" }
{ :stop_number => 1, :location => "Mom and Dads" }
{ :stop_number => 2, :location => "In-Laws" }
{ :stop_number => 3, :location => "Grandma's" }
{ :stop_number => 99, :location => "Time Square" }

在我看来非常优雅。谢谢@clyfe的提示!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-02 23:44:04

在Trip类中添加两个额外关系:

代码语言:javascript
复制
clss Trip
  has_many :pit_stops
  has_one :start_pit_stop, :class => 'PitStop', 
    :conditions => 'pit_stops.order_number == 1'
  has_one :end_pit_stop, :class => 'PitStop', 
    :conditions => 'pit_stops.order_number == trips.last_order_number'
end

对于start put_stop,您可以在== 1上设定条件,对于最后一列,您需要在trips表上增加一个列,在该表中缓存最后一个行程号。您还可以在父服务器上缓存这两个pit_stops的ids。通过这种方式可以进行急切的加载.

票数 3
EN

Stack Overflow用户

发布于 2012-01-02 23:29:23

嗯,如果在两次db访问中可以这样做,您可以使用

代码语言:javascript
复制
first_stop = t.pit_stops.order(:stop_number).first
last_stop = t.pit_stops.order(:stop_number).reverse_order.first
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8706335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档