2012-01-02 4 views
1

私はむしろRailsの新機能であり、表現力豊かなモデリングアーキテクチャを愛しています。私は現在、2つのテーブルの間に1対多数のリンクを持つルーティングシステムを構築しています。Rails 3.1で親行の最初と最後の子レコードを表示するにはどうすればよいですか?

は、次のスキーマを考えてみましょう:

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」行に最初と最後のPitStopの位置。私はちょうど私が始めたとどこが終了した場所を知りたい、との間でピットがで停止して気にしないでください:

-------- 
My Trips 
-------- 

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

私はすべて「中-間の」クエリからピットストップを排除したいのですが、各旅行にはかなりの数があるためです。

質問:ActiveRecordを使用してこのデータをdbからプルするにはどうすればよいですか?

ソリューション:月3日、2012

I旅行のモデルに私のピットストップロジックを適用することによって、私の問題を解決しました。 My FromとTo PitStopsにハードコードされたstop_number値が追加されました。それを実践した後、私は解決策が現実の世界にとって実際には理にかなっていることを発見しました(二重の勝利)。

  • からピットストップのレコードは常に0
  • のstop_number値がにピットストップのレコードは常に99

のstop_number値を持つことになりますしているので、これは理にかなっています最初のPitStopは実際には「ピットストップ」ではなく、どこから始めるのですか(つまり0)。最後のPitStopは実際には「ピットストップ」でもなく、最終位置(つまり99)です。もちろん、これは98以上の「ピットストップ」以上のルートはないと想定しています。 :)私にとって安全な仮定...

これらの論理的に定義された「stop_numbers」は、「trips/index」表示のためにすべての子PitStopsをクエリするための私の問題も解決します。 .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に入るトリックが今あなたのstarting_fromending_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") 

マイ(注文)ピットストップのレコードは、次のようになります。私の意見では

{ :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!それは2デシベル旅行でそれを行うために、OKであれば

答えて

3

を使用することができます。開始について

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 

をすることができますput_stop条件== 1、最後のトリップ番号をキャッシュするtripsテーブルに余分な列が必要です。これらの2つのpit_stopsのIDを親にキャッシュすることもできます。 あなたは熱心な負荷をかけることができます。

0

さて、あなたは、トリップクラスに2つの余分な関係を追加

first_stop = t.pit_stops.order(:stop_number).first 
last_stop = t.pit_stops.order(:stop_number).reverse_order.first 
+0

ありがとうございました。私はこれが@Durrantの提案と非常によく似ているが、より表現力があることがわかりました。私は努力を感謝しますが、私もpit_stopsの全リストを照会し、最初と最後を検索する必要があることを恐れています(順序を逆にして最初のものを取得することによって)。 :)考えをありがとう...もう一度、私は単一のクエリで最初と最後をクエリする方法を探しています。他のアイデア? – Luc

関連する問題