2010-07-27 7 views
9

목표 : CRON 작업 (또는 다른 예약 된 이벤트)을 사용하여 야간으로 기존 시스템에서 데이터를 내보내 데이터베이스를 업데이트합니다.Rails 작업을 작성하여 Rails 응용 프로그램으로 데이터를 가져 오시겠습니까?

모든 데이터는 기존 시스템에서 작성/업데이트/삭제됩니다. 웹 사이트는이 시스템과 직접 통합하지 않으므로 레일 앱은 단순히 데이터 내보내기에 나타나는 업데이트를 반영해야합니다.

나는 다음과 같습니다 ~ 5,000 제품의 .txt 파일이 :

모든 값은 콜론

필드는 (:)

로 구분됩니다 따옴표 ( ")로 묶인 문자열
"1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222" 
"A134":"another product":"attr 1":"attr 2":"Foobar World":"2447" 
... 

:

  • id : 고유 ID; 영숫자
  • name : 제품 이름; 임의의 문자
  • 속성 열 : 문자열; 모든 문자 (예 : 크기, 무게, 색상, 크기)
  • vendor_name : string; 모든 문자
  • vendor_id : 고유 공급 업체 ID; 숫자

현재 시스템에서 공급 업체 정보가 정규화되지 않았습니다.

모범 사례는 무엇입니까? 제품 및 공급 업체 테이블을 삭제하고 매주기마다 새 데이터로 다시 쓸 수 있습니까? 또는 새로운 행을 추가하고 기존 행을 업데이트하는 것이 더 낫습니다.

노트 :

  1. 이 데이터는 매일 밤 데이터베이스 수입을 통해 지속됩니다 Orders을 생성하는 데 사용됩니다. OrderItems은 데이터 파일에 지정된 제품 ID에 연결해야하므로 각 가져 오기에 대해 자동 증가 기본 키를 동일하게 사용할 수 없습니다. 고유 한 영숫자 ID는 products에서 order_items에 참여하는 데 사용해야합니다.
  2. 이상적으로는, 나는 바닐라 SQL 문을 사용할 수 없습니다
  3. 공급 업체 데이터를 정상화하기 위해 수입을하고 싶습니다, 그래서 내가 Product.create(...)Vendor.create(...) 스타일의 구문을 사용하기 위해 rake 작업을 작성해야 상상한다.
  4. 이는 EngineYard

답변

14

나는 제품을 삭제하고 모든주기에 테이블을 벤더 않을 것이다 구현됩니다. 레일 앱인가요? 그렇다면 ActiveRecord 헬퍼가있어서 도움이 될 것입니다.

p = Product.find_or_initialize_by_identifier(<id you get from file>) 
p.name = <name from file> 
p.size = <size from file> 
etc... 
p.save! 

가 find_or_initialize 사용자가 지정한 ID로 데이터베이스에 제품을 조회하며, 그것을 찾을 수없는 경우, 그것은 것입니다 :

당신이 제품 액티브 레코드 모델이있는 경우, 당신은 할 수있다 새 것을 만드십시오.이 방법을 사용하는 것이 매우 편리합니다. ActiveRecord는 데이터가 변경된 경우에만 데이터베이스에 저장하고 그에 따라 테이블에있는 모든 타임 스탬프 필드를 자동으로 업데이트합니다 (updated_at). 한 번 더, 식별자 (파일에서 ID)로 레코드를 찾고있을 것이므로 데이터베이스의 해당 필드에 인덱스를 추가해야합니다.

이렇게하려면 레이크 작업을하려면 rails 파일을 레일 응용 프로그램의 lib/tasks 디렉토리에 추가하십시오. 우리는 그것을 data.rake라고 부를 것입니다. , 레이크 작업을 호출하는 것보다

namespace :data do 
    desc "import data from files to database" 
    task :import => :environment do 
    file = File.open(<file to import>) 
    file.each do |line| 
     attrs = line.split(":") 
     p = Product.find_or_initialize_by_identifier(attrs[0]) 
     p.name = attrs[1] 
     etc... 
     p.save! 
    end 
    end 
end 

사용 data.rake 내부

, 그것은 다음과 같이 보일 것입니다 : 명령 줄에서 "레이크 데이터 가져 오기".

+0

이 시도하지만 난 주에 대한 오류'정의되지 않은 지역 변수 또는 메소드의 데이터를 '받고 있어요 : Object'합니다. 이것이 일어날 수있는 모든 생각? – Nick

+0

문제는'네임 스페이스 데이터를'네임 스페이스 : 데이터 할 '로 변경해야한다는 것이 었습니다. – Nick

0

제품이 실제로 자주 변경되지 않으므로 내가 보는 가장 좋은 방법은 변경되는 레코드 만 업데이트하는 것입니다.

  1. 하나의 SQL 문을 사용하여 모든 델타을
  2. 대량 업데이트하기

당신이 모델에 정규화 코드가있는 경우, 당신은 Product.create 및 Vendor.create 그렇지 않으면 사용할 수 과잉 일뿐입니다. 또한 단일 SQL 트랜잭션에 여러 레코드를 삽입하는 방법을 살펴보십시오.

+0

내 질문에 언급 된대로, 나는 __cannot__ 바닐라 SQL 문을 사용합니다. –

0
  • 가 빠른 CSV 또는 바닐라 루비 등을 통하여 사용 라인으로 파일 라인을 구문 분석 cronned되는 수입 레이크 작업 만들기 :

file.each가 할 | 행 | products_array = line.split ("") 끝

  • 분할의 각 라인 ":"와 같은 당신의 DB를 채울 find_or_initialize를 사용하여 해시
  • 로 밀어 :

    Product.find_or_initialize_by_name_and_vendor_id ("foo는"111)

+0

왜 'find_or_initialize_by_name_and_vendor_id'를 사용하고 있습니까? 이것은 'accepts_nested_attributes_for : vendor' 제품을 제안합니까? –

관련 문제