2014-02-20 5 views
5

Скажем, у меня есть следующий класс:Использование преобразователей заголовка рубин CSV

class Buyer < ActiveRecord::Base 
    attr_accesible :first_name, :last_name 

и следующее в файл CSV:

First Name,Last Name 
John,Doe 
Jane,Doe 

Я хочу, чтобы сохранить содержимое CSV в базу данных. У меня есть следующие в файле Рейк:

namespace :migration do 
    desc "Migrate CSV data" 
    task :import, [:model, :file_path] => :environment do |t, args| 
    require 'csv' 

    model = args.model.constantize 
    path = args.file_path 
    CSV.foreach(path, :headers => true, 
         :converters => :all, 
         :header_converters => lambda { |h| h.downcase.gsub(' ', '_') } 
        ) do |row| 
    model.create!(row.to_hash) 
    end 
end 

конец

Я получаю undefined method 'downcase' for nil:NilClass. Если я исключаю конвертеры заголовков, то получаю unknown attribute 'First Name'. Каков правильный синтаксис для преобразования заголовка, например, First Name в first_name?

+1

Дайте ошибку полностью * undefined method 'downcase' *, которые помогут нам узнать, на каком объекте был вызван метод. –

+0

@ArupRakshit Отредактированный вопрос, это на 'nil: NilClass'. – jcm

+0

Просто добавьте туда одну запись: return_headers => true'. Я не тестировал, но надеюсь, что это сработает. Если это поможет, сообщите мне, я объясню вам все, что произошло. –

ответ

15

После выполнения некоторых исследований здесь, на моем рабочем столе, мне кажется, что ошибка для чего-то еще.

Сначала я положил данные в моем "a.txt" файл, как показано ниже:

First Name,Last Name 
John,Doe 
Jane,Doe 

Теперь я побежал код, который сохраняется в моем so.rb файле.

so.rb

require 'csv' 

CSV.foreach("C:\\Users\\arup\\a.txt", 
      :headers => true, 
      :converters => :all, 
      :header_converters => lambda { |h| h.downcase.gsub(' ', '_') } 
      ) do |row| 
    p row 
end 

Теперь запустив:

C:\Users\arup>ruby -v so.rb 
ruby 1.9.3p448 (2013-06-27) [i386-mingw32] 
#<CSV::Row "first_name":"John" "last_name":"Doe"> 
#<CSV::Row "first_name":"Jane" "last_name":"Doe"> 

Так что все теперь работает. Теперь позвольте мне воспроизвести ошибку:

Я положил данные в моем "a.txt" файл, как показано ниже (только что добавили , после последнего столбца):

First Name,Last Name, 
John,Doe 
Jane,Doe 

Теперь я побежал код, который сохраняется в моем so.rb файл, снова.

C:\Users\arup>ruby -v so.rb 
ruby 1.9.3p448 (2013-06-27) [i386-mingw32] 
so.rb:5:in `block in <main>': undefined method `downcase' for nil:NilClass (NoMethodError) 

Кажется, в вашей строке заголовка, есть пустое значение столбца, который вызывает ошибку. Таким образом, если у вас есть контроль над источником CSV файл, проверьте его же. Или сделать некоторые изменения в коде, чтобы обработать ошибку, как показано ниже:

require 'csv' 

CSV.foreach("C:\\Users\\arup\\a.txt", 
      :headers => true, 
      :converters => :all, 
      :header_converters => lambda { |h| h.downcase.gsub(' ', '_') unless h.nil? } 
      ) do |row| 
    p row 
end 
+0

Вы правы, где-то была дополнительная запятая, но, как ни странно, код по-прежнему нуждается в вашем первоначальном предложении ': return_headers => true' для работы. В противном случае он дает ошибку «undefined attribute:». – jcm

+0

@jcm Тогда добавьте это, но без ': return_headers => true' код для меня пробежал как ожидалось. –

7

Более общий ответ, но если у вас есть код, который нужно обрабатывать как текст, а иногда вы можете получить ноль там, затем вызовите to_s на объект. Это превратит нуль в пустую строку. например

h.to_s.downcase.gsub(' ', '_') 

Это никогда не будет взрывать, независимо Н, потому что каждый класс рубин имеет метод to_s, и она всегда возвращает строку (если только вы не переопределены это делать что-то другое, что было бы нежелателен).

Смежные вопросы