【问题标题】:Adding Together and Humanizing Time in Rails在 Rails 中添加时间并人性化
【发布时间】:2014-08-29 14:30:58
【问题描述】:

我有一个专辑模型,每张专辑都有很多曲目:

#app/models/album.rb
class Album < ActiveRecord::Base
  has_many :tracks
end

#app/models/album.rb
class Track < ActiveRecord::Base
  belongs_to :album
end

每个单独的轨道都有一个带有时间模型类型的持续时间。为了显示每张专辑的所有曲目,我设置了以下显示操作:

#app/controllers/albums_controller.rb
def show
  @tracks = @artist.tracks.all
end

更新:显示持续时间如何存储在我的 _form.html.erb 中

#app/views/tracks/_form.html.erb
<div class="field">
  <%= f.label :duration %><br>
  <%= f.time_select :duration, include_seconds: true, default: {hour: '00', minute: '01', second: '30'} %>
</div>

--

这就是问题发生的地方。我基本上想将所有轨道持续时间加在一起,并以人类可读的格式显示它们。例如,一张专辑Total Runtime 将是 1 小时 13 分钟。我将持续时间加在一起的第一反应是使用注入方法:

#apps/views/albums/show.html.erb
.
.
.
<% @tracks.inject(0) {|sum, track|  track.duration.to_s(:time) + sum} %>
  • 我最终得到了这个错误:no implicit conversion of Fixnum into String

  • 我的第二个问题是进一步配置to_s(:time) 方法。曲目通常显示如下:3:30,意思是 (x)minutes : (x)seconds。不幸的是to_s(:time) 限制你只显示小时和分钟,而我只需要分钟和秒。

  • 为了最终获得总持续时间,我不完全确定这样做的最佳方法是什么。有没有办法将注入方法的结果保存为名为 runtime 的变量并像这样包装它,同时删除 distance_of_time_in_words 方法附带的 About 文本?

&lt;p&gt;&lt;b&gt;Total Runtime:&lt;/b&gt;&lt;%= runtime.distance_of_time_in_words %&gt;&lt;/p&gt;

【问题讨论】:

  • 您如何存储时间值?我的建议是以秒为单位存储所有值(例如,3:11 的曲目将是 191 秒),然后在适当的模型/助手中进行数学/格式化。
  • @thankyour 这就是我需要帮助的地方。我使用 rails 为时间属性提供的默认选择框存储时间值。
  • @thankyour 希望我上面提供的部分表单能给你一个更好的主意。
  • @CarlEdwards 嗯...我不认为time_select 是你的朋友。您可以仅将其替换为 select 并自己填充值,或者将其设为 number_select 并在模型中进行数学运算?您甚至可以将其设置为视图中的文本字段并自己执行验证(确保输入了数字)?
  • @thankyour 你能给我举个例子吗?其中很多对我来说仍然是新的。

标签: ruby-on-rails ruby model-view-controller methods


【解决方案1】:

这是一个很长的例子:

app/models/concerns/time_format.rb

# module to contain method used by both Album and Track
module TimeFormat
  extend ActiveSupport::Concerns

  def to_time(total_time)
    minutes, seconds = total_time.to_i.divmod(60)
    return [minutes, seconds]
  end
end

app/models/track.rb

class Track < ActiveRecord::Base
  include TimeFormat
  belongs_to :album
  attr_accessor :minutes, :seconds
  validates :length, :minutes, :seconds, numericality: {only_integer: true}
  before_update :to_seconds

  minutes, seconds = to_time(length)

  def to_seconds
    length = (minutes * 60) + seconds
  end
end

希望这将为您指明正确的方向:

app/models/album.rb

class Album < ActiveRecord::Base
  include TimeFormat
  has_many :tracks
  attr_accessor :length, :minutes, :seconds
  validates :length, :minutes, :seconds, numericality: {only_integer: true}

  def calculate_length
    self.tracks.each do |track|
      length += track.length
    end
  end

  minutes, seconds = to_time(self.calculate_length)

end

app/controllers/albums_controller.rb

# If your controller was generated with scaffolding, no need to change the `show` method.
# It should already be loading an album object for you via the `before_action` callback.
# The only thing to make sure is that you change accepted parameters for the create and
# update methods (do the same thing in Tracks if you need to).

def album_params
  params.require(:album).permit(:minutes, :seconds, <other params>...)
end

app/views/tracks/_form.html.erb

# You can use this same field in your Album view.

<div class="field">
  <%= f.label :minutes %><br>
  <%= f.number_field :minutes  %>
  <%= f.label :seconds %><br>
  <%= f.number_field :seconds %>
</div>

我还不是一个经验丰富的 Rails 开发人员,所以这些示例中的某些部分可能可以精简,但我希望这能传达一般意义!

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 2011-06-04
    • 2013-10-06
    • 2021-09-20
    相关资源
    最近更新 更多