2009-06-26 10 views
27

레일스 모델에서 기간 필드를 사용하는 가장 좋은 방법을 찾고 있습니다. 형식을 HH : MM : SS (예 : 01:30:23)로하고 싶습니다. 사용중인 데이터베이스는 로컬에서 sqlite이고 프로덕션에서는 Postgres입니다.레일스 모델에서 기간 필드 사용

나는 또한 내가 현장에있는 모든 개체를 살펴보고 해당 모델의 모든 개체의 총 시간을 마련와 같은 끝낼 수있는이 분야에 일하고 싶습니다 :

30 레코드는 총 45 시간 25 분 34 초입니다.

그래서 무엇이 가장 좋을까요? 침전물 형태의 이주

  • 양식 필드

    • 필드 형식 (시간, 분, 초 드롭 다운?)
    • 가장 저렴한 방법은 모델의 모든 레코드의 총 지속 시간을 발생
  • 답변

    41
    • 데이터베이스에 정수로 저장합니다 (아마도 초 수).
    • 입력 양식은 정확한 사용 사례에 따라 다릅니다. 드롭 다운은 고통 스럽습니다. 시간 + 분 + 초 단위의 작은 텍스트 필드를 사용하는 것이 좋습니다.
    • 지속 기간 열에 대해 SUM 쿼리를 실행하여 총계를 생성하기 만하면됩니다. 정수를 사용하면 쉽고 빠릅니다. 또한

    는 :

    • 은 뷰의 지속 시간을 표시 할 도우미를 사용합니다.(123을 데이터베이스의 정수로 바꾸십시오)을 사용하여 지속 시간을 ActiveSupport::Duration으로 쉽게 변환 할 수 있습니다. 좋은 서식을 얻으려면 Durationinspect을 사용하십시오.
    • 모델에서 정수가 아닌 ActiveSupport::Duration 개체를 반환하거나 가져 오는 특성 판독기 및 작성기가 필요할 수 있습니다. duration=(new_duration)duration을 간단히 정의하십시오. 내부적으로 정수 인수를 사용하여 read_attribute/write_attribute을 호출합니다.
    +0

    +1 내 의견을 게시하는 데 걸리는 시간이 짧습니다. :) –

    +0

    나는 초를 사용하는 것을 고려하지 않았다, doh! 팁 고마워! – mwilliams

    +0

    출력을 포맷하기 위해'inspect'를 어떻게 사용합니까? 예? –

    5

    ActiveSupport :: Duration을 사용해 보았지만 출력이 분명하지 않습니다.

    ruby-duration은 정확도와 시간을 초 단위로 나타내는 불변 유형입니다. 그것은 많은 테스트와 몽고이드 모델 필드 타입을 가지고 있습니다.

    나는 인간의 지속 시간 문자열을 쉽게 파싱하여 Chronic Duration으로갔습니다. 다음은 초 단위 time_spent 필드가있는 모델에이를 추가하는 예제입니다.

    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 
    
    3

    내가 지원하고 ActiveRecord::Duration으로 PostgreSQL을의 interval 유형을 사용하는 일부 스텁을 작성했습니다.

    이 요점을 참조하십시오 (레일 4의 초기화 프로그램으로 사용할 수 있습니다.1) : https://gist.github.com/Envek/7077bfc36b17233f60ad

    또한 내가 연 끌어 오기가 레일 요청 : 레일 5에서 https://github.com/rails/rails/pull/16919

    +0

    레일즈 5.1 용 업데이트 요령을 작성했습니다 : https://gist.github.com/vollnhals/a7d2ce1c077ae2289056afdf7bba094a –

    4

    , 당신은 ISO8601 문자열로 ActiveSupport :: 재생 시간을 저장하는 속성 :: 액티브을 사용할 수 있습니다. 정수보다 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