1

属性を持つモデルPlanningがありstart_timeます。午前9時から午後12時の間、または午後6時から午後11時までのすべての計画を取得したいとします。

基本的に私はします:

Planning.where do 
     (start_time >= @start_time[0]) & (start_time <= @end_time[0]) 
     | 
     (start_time >= @start_time[1]) & (start_time <= @end_time[1])
end

問題は、タイムスロットの数が異なるということです...何か考えはありますか?

それが助けになるなら、私はSqueelgemを使います。

前もって感謝します!

4

3 に答える 3

3

whereブロック内で好きなことをすることができます。ただし、これがwhere句として使用されるため、最後に実際のクエリを返す必要があります。

したがって、次のような時間の配列が与えられます:

times = [ [ '09:00:00', '12:00:00' ], [ '18:00:00', '23:00:00' ] ]

詳細な解決策は次のとおりです。

Planning.where do
  query = nil

  times.each do |a,b|
    q = (start_time >= a) & (end_time <= b)

    if query
      query |= q
    else
      query = q
    end
  end

  query
end

より賢い解決策は次のとおりです。

Planning.where do
  times.map { |a,b| (start_time >= a) & (end_time <= b) }.reduce(&:|)
end

どちらも次のSQLを生成します。

SELECT "plannings".* FROM "plannings"
WHERE ((
  ("plannings"."start_time" >= '09:00:00' AND "plannings"."end_time" <= '12:00:00')
  OR
  ("plannings"."start_time" >= '18:00:00' AND "plannings"."end_time" <= '23:00:00')
))
于 2012-11-24T10:30:52.807 に答える
1

ルビーコードで生成されたSQLをコピーして貼り付けてもらえますか?

編集

さて、私はあなたの問題を理解し、それが明確ではなかったと質問します。コードを読みやすくしたい場合は、この場合、squeelの代わりにARelを使用する必要があります(少なくとも、このために作成されていないDSLは使用しないでください)。マップ関数を適用してから、すべてをORで結合できるはずです。

于 2012-11-23T08:50:07.413 に答える
0

where()メソッドがAR:Relationを返しているのではないですか?

これで、where()呼び出しをチェーンできるようになります。

finder = Planing.scoped 
time_slots.each do |start_time, end_time|
    finder = finder.where{(start_time >= my{start_time}) & (start_time <= my{end_time}) }
end

私はこのコードを試していませんが、うまくいかない理由はわかりません

編集:あなたが述べたように、これは条件をORではなくANDとリンクします

次のことを試してみませんか?

Planning.where do 
    time_slots.inject(false) do |memo, time_slot| 
        memo | (start_time >= time_slot.first) & (start_time <= time_slot.last)
    end
end 

これは、squeelのinstance_evalを操作するには少し魔法が多すぎるかもしれませんが、試してみてください:)

于 2012-11-23T08:31:25.547 に答える