2013-03-07 6 views
1

내가 3레일 작업 레이크 - 이미

나는 두 개의 CSV 파일이 (gas.csv & elec.csv 레일의 ​​새로운 레이크 작업을 만들려고 해요 존재하지 않는 경우 CSV 파일을 구문 분석 및 가져 오기) 사용 데이터는 SQL 데이터베이스에서 15 분마다 업데이트됩니다. 다음의가있는 CSV의 형식은 (나는이 제어 할 수 없습니다) :

MeterID,RoundedTimeStamp,Value,Register 
165,31/01/2012 00:00,1200,0 
165,28/02/2012 00:15,1201,0 
165,31/03/2012 00:30,1199,0 

의 새로운 값으로 매월 업데이트되는 CSV는, 나는 가져올 레이크 가져 오기 작업을 쓰고 싶어 모델의 관련 부분으로 파일, 사용 (월, 일렉트릭, 가스).

require 'csv' 
desc "Importing Usage data from CSV file" 
task import: :environment do 

    file = ".../elec.csv" 

    CSV.foreach(file, headers: true) do |row| 
      Usage.find_or_create_by_month({ 
       month: row[1], 
       elec: row[2] 
      }) 
    end 
end 

내가 레이크을 실행합니다 : 지금까지 나는 정말 작동하지 않는 ELEC 수입에 대해 다음있어 콘솔에서 가져 오기, 그냥 벌금 ELEC 사용 데이터를 가져옵니다,하지만하지 않습니다 중복을 건너 뜁니다. 중복없이이 파일을 가져올 수있는 방법이 있습니까? 또한 가스 데이터에 대해 동일한 작업을 수행 할 수있는 방법이 있습니까?

참고 : find_or_create보다는 first_or_create를 사용하는 것이 더 바람직하지만 _by_month와는 작동하지 않습니다.

건배! 당신은 Upsert을 시도 할 수 http://apidock.com/rails/ActiveRecord/Relation/first_or_create

+0

'어디에 (월 : 행 [1]). first_or_create', find_or_create 레일에 사용되지 Methos는 목록에 있어야합니다 4. – Leito

+0

그래, 나는 APIdock에서 그것을 처음 보았다. 그러나 그것은 작동하지 않았다! – KevL

답변

2
User.where(month: row[1]).first_or_create do |user| 
    user.elec = row[2] 
end 

상세 정보 :

require 'upsert' 
require 'active_support/core_ext' # you'll already have this in Rails 
# ... 
u = Upsert.new Usage.connection, Usage.table_name 
# ... 
CSV.foreach('elec.csv', headers: :first_row) do |row| 
    date = Date.parse row['RoundedTimeStamp'] 
    selector = { meter_id: row['MeterID'], month: date.strftime('%Y-%m') } 
    setter = { elec: row['Value'] } 
    u.row selector, setter 
end 
CSV.foreach('gas.csv', headers: :first_row) do |row| 
    date = Date.parse row['RoundedTimeStamp'] 
    selector = { meter_id: row['MeterID'], month: date.strftime('%Y-%m') } 
    setter = { gas: row['Value'] } 
    u.row selector, setter 
end 

당신의 "달"열이 문자열 필드의 경우, 다음이 작동합니다. 그것은 실제 날짜 필드가 있다면, 당신은 매월 첫 번째 사용하여 시도 할 수 있습니다 :

date.strftime('%Y-%m-01') 
+0

이것은 작동하지 않는 것 같습니다. 이미 존재하는 경우에도 새 레코드를 만듭니다 (내 자신과 동일한 기능). – KevL

+1

@KevL, 이걸 독자적으로 시도 했습니까? 나는 콘솔에서 시도했고 제공된 예제처럼 작동했습니다. 문제를 최소한으로 줄이고 어디에서 실패하는지 확인해 보겠습니다. – Leito

+0

아 - 내가 어디로 잘못 가고 있는지 알 겠어. RoundedTimeStamp는 DateTime 형식이고 내 월 열은 날짜 형식이므로'month : row [1] .to_date '를 추가하여 수정했습니다. 감사! 'usage.elec = row [2]'를 사용하거나'.first_or_create (elec : row [2]) '를 사용하는 것이 더 빠르다는 것을 알고 계십니까? – KevL

1

에서

+0

"위와 같은 파일을로드 할 수 없습니다"오류가 발생합니다. 또한, 헤더가 "RoundedTimeStamp"이므로 행 [1]에 맞다고 확신합니다. – KevL

+0

"upsert"를 Gemfile에 추가 하시겠습니까? –

+0

아하 ... 아주 분명해! 어떤 생각도 내가 기존의 달 동안 가스를 수입하기 위해 이것을 할 수 있었던 방법? – KevL