Я довольно новичок в 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 |
--------------------------------------------------------
Я бы хотел исключить все промежуточные PitStops из запроса, поскольку их будет достаточно для каждой поездки.
Вопрос : Каков наилучший способ извлечь эти данные из БД с помощью ActiveRecord?
Решение: 3 января 2012 г.
Я решил свою проблему, применив логику PitStop к модели Trip. Мои From и To PitStops теперь имеют жестко закодированные значения stop_number. Проработав его, я обнаружил, что решение действительно имеет смысл и для реального мира (двойная победа).
- Запись From PitStop всегда будет иметь значение stop_number, равное 0.
- Запись PitStop К всегда будет иметь значение stop_number 99.
Это имеет смысл, потому что первый 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
Как видите, хитрость для ввода 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 за подсказку!