0

我正在尝试将 ActiveRecord 对象中的 MySQL 时间戳转换为另一种时间戳格式。我的方法采用一个 ActiveRecord 记录数组并返回一个哈希数组,其中包含带有格式化时间戳的时间戳字段:

def convert_mysql_timestamps(records)
    ary = []
    hash = {}
    records.each_with_index do |record, i|
      record.attributes.each do |field, value|
        if time_columns.include?(field) and value then
          hash[field] = value.strftime("%Y-%m-%dT%H:%M:%S%z")
        else
          hash[field] = value
        end
      end
      ary[i] = {}
      ary[i] = hash
    end
    ary
  end

但是,在ary[i] = hash分配时,所有ary元素都设置为散列。

有没有更好的方法来转换记录的时间戳字段?(我不需要将记录保存回数据库。)另外,如何让数组捕获记录的每个单独的哈希表示?

输入:

[#<Vehicle id: 15001, approved_at: "2011-03-28 10:16:31", entry_date: "2011-03-28 10:16:31">, #<Vehicle id: 15002, approved_at: "2011-03-28 10:16:31", entry_date: "2011-03-28 10:16:31">]

期望的输出:

[{"id"=>15001, "approved_at"=>"2011-03-28T10:16:31-0700", "entry_date"=>"2011-03-28T10:16:31-0700"}, {"id"=>15002, "approved_at"=>"2011-03-28T10:16:31-0700", "entry_date"=>"2011-03-28T10:16:31-0700"}]
4

3 回答 3

1

问题是您正在创建一个哈希:

def convert_mysql_timestamps(records)
  ary = []
  hash = {}
  #...

然后尝试为每条记录重复使用。您可能希望每次each_with_index迭代都有一个新的哈希:

  def convert_mysql_timestamps(records)
    ary = []
    records.each_with_index do |record, i|
      hash = { }
      record.attributes.each do |field, value|
        #...
      end
      ary[i] = hash
    end
  end
于 2013-01-16T01:17:01.160 回答
0

您可以使用map它 - 当您想要以一种格式获取数组并以另一种格式生成相同大小的数组时,它始终是一个不错的选择。就是这样:

def convert_mysql_timestamps(records)
  records.map do |record|
    Hash[records.attributes.map{|k, v| [k, convert_mysql_timestamp(v)] }]
  end
end

def convert_mysql_timestamp(field, value)
  return value unless time_columns.include?(field) && value
  value.strftime("%Y-%m-%dT%H:%M:%S%z")
end

它是这样工作的:

  • Hash[array_of_pairs]将键值对数组 - 像[["foo", 2], ["bar", 3], ...]- 变成像{"foo" => 2, "bar" => 3, ...}.

  • map为集合中的每个项目调用其块,并将块的每个返回值收集到一个新数组中,然后返回。内部创建键值对数组,外部attributes.map将所有哈希收集到返回的数组中。Hash[...]records.map

我建议阅读Enumerable中的方法,因为那里有很多类似map的东西。你会发现你几乎不需要在你的循环中使用索引,尽管如果你来自另一种语言并且for到处都有循环,那么你很难改掉这个习惯!

于 2013-01-16T01:23:41.137 回答
0

我不确定你time_columns是什么,但假设它们是Time类,你可以简化部分,如value.is_a?(Time).

def convert_mysql_timestamps(records)

 records.collect do |record|
   # assuming records are from a Rails model, I am using #attributes 
   # to loop through all fields in a record 
                    # then inject values in this hash -> ({}), 
                    # which is in the block, named attributes
   record.attributes.inject({}) do |attributes, (column_name, value)|
     # if it is Time, convert it to iso8601 (slightly different from your format, 
     # but if this is also acceptable, your code can be simpler)
     attributes[column_name] = (value.is_a?(Time) ? value.iso8601 : value)
     attributes
   end
 end

end
于 2013-01-16T02:49:25.630 回答