2014-03-02 10 views
0

CSV 파일을 데이터베이스로 가져 오지만 어울리지 않는 속성 이름 때문에 장소가 변경되는 데 문제가있는 코드가 있습니다. 이 같은 CSV 파일 모양에루비 해시로 헤더 이름 변경하기

헤더 :

Date,Visitors 
02/01/2014,3483 
01/01/2014,13636 

내 데이터베이스가 같은 필드가 있습니다하지만 그들은 처음에 대문자를 사용하지 않는 : 나는을 가져올 때

date 
visitors 

파일을 잘 작동하지만 파일의 값을 수동으로 편집하고 헤더를 소문자로 변경하여 가져 오기에서 일치시켜야합니다. 여기 내 모델에서 내 수입 방법 :

def self.import(file) 
    CSV.foreach(file.path, headers: true) do |row| 
     entry = find_by(date: Date.parse(row["Date"])) || new 
     entry.update row.to_hash 
     entry.save! 
    end 
end 

는 데이터베이스로 가져 와서 실패하기 전에 내 방법은 해시 헤더 이름을 변경 할 수있는 쉬운 방법이 있는지 궁금 해요, 그래서 내가 제거 할 수 있습니다 직접 파일 편집의 수동 개입.

.slice 메소드를 살펴 보았지만 특정 속성을 선택하는 것처럼 보이지만,이를 대체하는 .map을 사용하여 순수 루비를 찾았지만 레일에 더 적합한 것이 포함되어 있는지 궁금합니다. 태스크?

읽어 주셔서 감사합니다.

+0

당신은 소문자로 헤더 필드를 변경하려면? 이게 당신의 필요입니까? –

답변

2

:header_converters => [:downcase]으로 옵션 하나를 추가하기 만하면됩니다. 이 옵션을 추가하면 헤더 문자열에서 String#downcase 메서드를 호출합니다. 아래의 코드에서

봐 당신에게 힌트를주고 그래서

require 'csv' 

str = <<_ 
Date,Visitors 
02/01/2014,3483 
01/01/2014,13636 
_ 

File.write('a',str) 

CSV.foreach('a',:headers => true,:header_converters => [:downcase]) do |row| 
    p row.to_hash 
end 
# >> {"date"=>"02/01/2014", "visitors"=>"3483"} 
# >> {"date"=>"01/01/2014", "visitors"=>"13636"} 

를, 당신의 방법은 다음과 같습니다

def self.import(file) 
    CSV.foreach(file.path, headers: true, :header_converters => [:downcase]) do |row| 
     entry = find_by(date: Date.parse(row["date"])) || new 
     entry.update row.to_hash 
     entry.save! 
    end 
end 
+0

이것은 나에게 효과가있는 것 같지 않습니까? 항목에 대해 불평하는 String에 nil을 암시 적으로 변환하지 않습니다. entry = find_by (date : Date.parse (row [ "Date"])) || 새로운 .. 어떤 아이디어? – calabi

+0

@calabi 오 이런 ..'행 [ '날짜']'로 쓰기 ... ... –

+1

아 물론! 그것은 변경된 후에도 효과가 없었을 것입니다. 내가 그걸 발견 했어야 했어, 정말 고마워! – calabi

1

공상 아무것도 필요 없음, 그냥 #update를 호출하기 전에 해시를 조작 :

def self.import(file) 
    CSV.foreach(file.path, headers: true) do |row| 
    entry = find_by(date: Date.parse(row["Date"])) || new 

    attributes = row.to_hash 
    attributes[:visitors] = attributes.delete("Visitors") 
    attributes[:date]  = attributes.delete("Date") 

    entry.update(attributes) 
    entry.save! 
    end 
end 

Hash#delete는 해시에서 항목을 제거하고 그 값을 반환합니다. 해시에서 속성 (예 : "Visitors""visitors")을 모두 사용하지 않으려는 경우 삭제하도록 선택했습니다. 경우

거기 CSV에 대한 자세한 속성은 당신이 하나씩 나열하고 싶지 않아, 당신은 약간 더 강력한 솔루션으로 이동 할 수 있습니다 :

CSV_MAP = { 
    'Date'  => 'date', 
    'Visitors' => 'visitors', 
    # More attributes... 
} 

def update_with_csv_row(row) 
    attributes = CSV_MAP.each_with_object({}) do |(csv_key, attribute_key), result| 
    result[attribute_key] = row[csv_key] 
    end 

    update(attributes) 
end 

그리고, 단지 #update_with_csv_row 전화 원래 코드에 #update 대신.

+0

정말 감사합니다! 미래에이 정보가 필요하다는 것을 알 수 있습니다. 참조 용으로 좋습니다. – calabi

관련 문제