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

問題は、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 に答える