【发布时间】:2012-01-02 23:21:17
【问题描述】:
我对 Rails 比较陌生,只是喜欢它富有表现力的建模架构。我目前正在构建一个在两个表之间具有一对多链接的路由系统。
考虑以下架构:
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
现在考虑一下单次旅行的以下数据:
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" })
我想做的是在“行程/索引”视图的单个“行程”行中显示所有行程名称的列表以及第一个和最后一个 PitStop 的位置。我不在乎中间的进站,我只想知道我从哪里开始,我在哪里结束:
--------
My Trips
--------
--------------------------------------------------------
| Route Name | From | To |
--------------------------------------------------------
| Christmas Visits Route | Home | Time Square |
--------------------------------------------------------
我想从查询中删除所有“中间”PitStop,因为每次行程都会有很多。
问题:使用 ActiveRecord 从数据库中提取这些数据的最佳方法是什么?
解决方案:2012 年 1 月 3 日
我通过将 PitStop 逻辑应用于 Trip 模型解决了我的问题。我的 From 和 To PitStops 现在有硬编码的 stop_number 值。完成后,我发现该解决方案实际上也适用于现实世界(双赢)。
- From PitStop 记录的 stop_number 值始终为 0。
- To PitStop 记录的 stop_number 值始终为 99。
这是有道理的,因为第一个 PitStop 根本不是真正的“进站”,它是您开始的地方(即 0)。最后一个 PitStop 也不是真正的“进站”,它是您的终点位置(即 99)。当然,这是假设任何路线都不会有超过 98 个“进站”。 :) 对我来说是安全的假设......
这些逻辑定义的“stop_numbers”还解决了我查询所有子 PitStop 以显示“行程/索引”的问题,并且我可以在每次行程中快速有效地查询这些值(不再需要对 .first 或 @987654326 进行子查询@):
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
如您所见,输入 stop_numbers 的技巧现在是在定义 starting_from 和 ending_at 记录(现在是逻辑业务规则)之后的简单数学方程式。现在我可以简单地说:
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 记录现在如下所示:
{ :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 的提示!
【问题讨论】:
标签: activerecord ruby-on-rails-3.1