34

Railsモデルでdurationフィールドを使用するための最良の方法を探しています。フォーマットをHH:MM:SS(例:01:30:23)にします。使用中のデータベースはローカルでsqliteであり、本番環境ではPostgresです。

また、このフィールドを操作して、フィールド内のすべてのオブジェクトを確認し、そのモデル内のすべてのオブジェクトの合計時間を計算して、次のようにすることができます。

合計45時間、25分、34秒の30レコード。

では、何が最も効果的でしょうか?

  • 移行のフィールドタイプ
  • CRUDフォームのフォームフィールド(時、分、秒のドロップダウン?)
  • モデル内のすべてのレコードの合計期間を生成するための最も安価な方法
4

4 に答える 4

44
  • データベースに整数として保存します(おそらく秒数)。
  • エントリーフォームは、正確なユースケースによって異なります。ドロップダウンは苦痛です。時間+分+秒の期間に小さなテキストフィールドを使用することをお勧めします。
  • 期間列に対してクエリを実行するだけで、SUM総計が生成されます。整数を使用する場合、これは簡単で高速です。

さらに:

  • ヘルパーを使用して、ビューに期間を表示します。(データベースの整数に置き換えてください)ActiveSupport::Durationを使用すると、期間を秒の整数として簡単に変換できます。結果に使用すると、適切なフォーマットになります。(完璧ではありません。自分で何かを書きたいと思うかもしれません。)123.seconds123inspectDuration
  • ActiveSupport::Durationモデルでは、整数ではなく、オブジェクトを返す/受け取る属性リーダーとライターが必要になる可能性があります。duration=(new_duration)とを定義するだけです。これは、整数引数を使用して/durationを内部的に呼び出します。read_attributewrite_attribute
于 2009-06-26T22:32:37.413 に答える
22

Rails 5では、ActiveRecord::Attributesを使用してActiveSupport::DurationsをISO8601文字列として保存できます。整数よりもActiveSupport::durationを使用する利点は、箱から出してすぐに日付/時刻の計算に使用できることです。あなたは次のようなことをすることができます、Time.now + 1.monthそしてそれは常に正しいです。

方法は次のとおりです。

追加config/initializers/duration_type.rb

class DurationType < ActiveRecord::Type::String
  def cast(value)
    return value if value.blank? || value.is_a?(ActiveSupport::Duration)

    ActiveSupport::Duration.parse(value)
  end

  def serialize(duration)
    duration ? duration.iso8601 : nil
  end
end

ActiveRecord::Type.register(:duration, DurationType)

移行

create_table :somethings do |t|
  t.string :duration
end

モデル

class Something < ApplicationRecord
  attribute :duration, :duration
end

使用法

something = Something.new
something.duration = 1.year    # 1 year
something.duration = nil
something.duration = "P2M3D"   # 2 months, 3 days (ISO8601 string)
Time.now + something.duration  # calculation is always correct
于 2017-07-27T19:11:08.643 に答える
6

ActiveSupport :: durationを使用してみましたが、出力を明確にするのに問題がありました。

あなたはruby-durationが好きかもしれません。これは、秒単位の精度で一定の時間を表す不変のタイプです。多くのテストとMongoidモデルフィールドタイプがあります。

人間の持続時間の文字列も簡単に解析したかったので、慢性的な持続時間を使用しました。これは、time_spentinsecondsフィールドを持つモデルに追加する例です。

class Completion < ActiveRecord::Base
  belongs_to :task
  belongs_to :user

  def time_spent_text
    ChronicDuration.output time_spent
  end

  def time_spent_text= text
    self.time_spent = ChronicDuration.parse text
    logger.debug "time_spent: '#{self.time_spent_text}' for text '#{text}'"
  end

end
于 2011-02-01T03:26:33.267 に答える
4

intervalPostgreSQLのタイプをサポートして使用するためのスタブをいくつか作成しましたActiveRecord::Duration

この要点を参照してください(Rails 4.1で初期化子として使用できます):https ://gist.github.com/Envek/7077bfc36b17233f60ad

また、Railsへのプルリクエストを開いています: https ://github.com/rails/rails/pull/16919

于 2014-09-12T10:44:22.807 に答える