我对Rails相当陌生,我很喜欢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" })我想要做的是为'trips/index‘视图在一个单独的" trip“行中显示所有trip名称的列表以及第一个和最后一个PitStop的位置。我不在乎中间站的位置,我只想知道我从哪里开始,在哪里结束:
--------
My Trips
--------
--------------------------------------------------------
| Route Name | From | To |
--------------------------------------------------------
| Christmas Visits Route | Home | Time Square |
--------------------------------------------------------我想从查询中删除所有的“中间”PitStops,因为每次旅行都会有很多。
问题:使用ActiveRecord从数据库中提取数据的最佳方法是什么?
解决方案:2012年1月3日
我通过将PitStop逻辑应用到Trip模型中来解决我的问题。我的From和To PitStops现在有了硬编码的stop_number值。在研究了它之后,我发现这个解决方案对于现实世界也是有意义的(双赢)。
F 214
这是有意义的,因为第一个PitStop根本不是真正的“停站”,它是你从哪里开始的。0)。最后一个PitStop也不是真正的“停站”,它是你的终点站。99)。当然,这假设任何路线都不会有超过98个“停站”。)对我来说安全的假设.
这些逻辑定义的"stop_numbers“还解决了我查询所有子PitStops以查找'trips/index‘显示的问题,并且我可以在每次旅行中快速有效地查询这些值(不再对.first或.last进行子查询):
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_from和ending_at记录(现在是逻辑业务规则)之后,输入stop_numbers的诀窍现在是一个简单的数学公式。现在我可以简单地说:
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的提示!
发布于 2012-01-02 23:44:04
在Trip类中添加两个额外关系:
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。通过这种方式可以进行急切的加载.
发布于 2012-01-02 23:29:23
嗯,如果在两次db访问中可以这样做,您可以使用
first_stop = t.pit_stops.order(:stop_number).first
last_stop = t.pit_stops.order(:stop_number).reverse_order.firsthttps://stackoverflow.com/questions/8706335
复制相似问题