2016-04-05 8 views
0

Offerの番号はplacesです。それは、毎日places予約がこのオファーのために作ることができることを意味します。 Offerhas_many予約。2つの日付間の予約が可能かどうかを確認する方法

A Bookingdate_begindate_endbelongs_toOfferを有しています。つまり、対応するOfferに関しては、date_begindate_endの間の1日が使用されます。

オファーのリクエストがあった場合、そのオファーを確認するにはどうすればよいですか?

例:ここでは

- offer has 2 places (offer.places == 2). 
- offer has currently 3 bookings (offer.bookings.count == 3) 
- First booking B1 is between 01-04-2016 and 10-04-2016 
- Second booking B2 is between 01-04-2016 and 05-04-2016 
- Third booking B3 is between 08-04-2016 and 10-04-2016. 

offer.available_between?("01-04-2016", "10-04-2016") 
=> false (because of B1 and B2, and because of B1 and B3) 

offer.available_between?("01-04-2016", "05-04-2016") 
=> false (because of B1 and B2) 

offer.available_between?("08-04-2016", "10-04-2016") 
=> false (because of B1 and B3) 

offer.available_between?("06-04-2016", "07-04-2016") 
=> true (because there is only B1 during this period) 

は、tryです:

class Offer < ActiveRecord::Base 

    # True if and only if each day between date_begin and date_end has at least one place left. 
    def available_between?(date_begin, date_end) 
    (date_begin.to_datetime.to_i .. date_end.to_datetime.to_i).step(1.day) do |date| 
     day = Time.at(date) 
     nb_places_taken_this_day = self.bookings.where("date_begin <= :date AND date_end >= :date", date: day).count 
     return false if nb_places_taken_this_day >= self.places 
    end 
    true 
    end 

end 

offer.available_between?(booking.date_begin, booking.date_end) 

複数の分離SQLクエリがあるので、私は特に、すべてこれで快適に感じることはありません。

ActiveRecordをより効率的に使用してこれを実現するより良い方法がありますか?

+0

? trueを返し、falseを返します。 例からわかるように、date_begin..date_end期間中に毎日適切な数の予約が行われた場合はtrueを返します。私は正しい? – SunnyMagadan

+0

私はそうは思わない。私は例を使って質問を更新し、もう少し明確にするためにメソッドを変更しました。ありがとう。 – rdupz

+0

ありがとうございますが、サンプル実装はまだ混乱しており、常にtrueを返します。サイクル内にreturn文がありませんでした(nb_places_taken_this_day> = self.placesの場合はfalseを返します)。 今度は、この期間の毎日の予約数が場所の数より少ない場合、あなたのメソッドはtrueを返すはずです。 – SunnyMagadan

答えて

1

私はこれを十分にテストするのに十分なデータがありませんが、これはうまくいくと思います。ここでは、開始日と終了日が要求された日付の前または後の両方でない予約が存在しないという条件をクエリに組み込みます。つまり、存在するすべての予約は、要求された開始前に開始と終了のいずれかが良い、または要求された終了後に開始と終了する方がよいでしょう。この条件を満たしていない予約が存在する場合、要求された日付は単一の予約として利用できません。これは機能しますか?

[EDIT - 実際の問題を反映して、元の壊れた答えから修正]

この新しい答えはまだ日をループし、しかし、1つのクエリ内のすべての競合の予約をつかん後にそうします。ルビーループ自体はかなり素早くなります。

(すべての?メソッドは、最初のfalse値でfalseを返し、すべての要素がtrueと評価されるとtrueを返すので、return false unlessを追加することは余計なことです。うまくいけば、意図を明確にするために、最後の行にreturnを追加しました」VEの。)私はあなたの説明を複数回読んだとavailable_betweenとき、まだ理解していない

def available_between?(date_begin, date_end) 
    conflicting_bookings = self.bookings.where.not("(date_begin < :requested_start_date AND date_end < :requested_start_date) OR (date_end > :requested_end_date AND date_end > :requested_end_date)", requested_start_date: date_begin, requested_end_date: date_end) 
    return (date_begin..date_end).all? do |day| 
     num_bookings_for_day = conflicting_bookings.select{|booking| booking.date_begin <= day && booking.date_end >= day}.count 
     num_bookings_for_day < self.places 
    end 
    end 
+0

私はそれが動作するとは思わない。私は例を追加します。 B1があなたのクエリと一致するので、 'available_between? 'の最後の実行は実装でfalseを返します。あなたは 'places'情報を見逃しています。ありがとう。 – rdupz

+0

申し訳ありませんが、場所についてのビットを逃しました。新しく修正された方法はそれをカバーしていますか? –

+0

本当に。 2カ所と3カ所の予約を申し出てください。予約は1日で、連続しています。この3日間はまだ1つの場所が残っているため(毎日)追加の予約*を行うことができます。あなたの質問は3つの相反する予約を返し、この追加の予約に失敗します。ただし、この例では、1日に1つの相反する予約のみ*があります。 – rdupz

関連する問題