Ruby on rails Rails:上传不带头的CSV文件

Ruby on rails Rails:上传不带头的CSV文件,ruby-on-rails,ruby,csv,file-upload,ruby-on-rails-3.2,Ruby On Rails,Ruby,Csv,File Upload,Ruby On Rails 3.2,我遵循railscasts#396导入CSV,并在我的rails项目中实现了CSV上传 这是我的视图文件: <%= form_tag import_customers_path, multipart: true do %> <%= file_field_tag :file %> <%= submit_tag "Import" %> <% end %> 以下是我的模型方法: def self.to_csv(options = {})

我遵循railscasts#396导入CSV,并在我的rails项目中实现了CSV上传

这是我的视图文件:

<%= form_tag import_customers_path, multipart: true do %>
  <%= file_field_tag :file %>
  <%= submit_tag "Import" %>
<% end %>
以下是我的模型方法:

def self.to_csv(options = {})
    CSV.generate(options) do |csv|
        csv << column_names
        all.each do |customer|
            csv << customer.attributes.values_at(*column_names)
        end
    end
end

def self.import(file)
  CSV.foreach(file.path, headers: true) do |row|
    Customer.create! row.to_hash
  end
end
def self.to_csv(选项={})
CSV.生成(选项)do | CSV|

csv您可以将csv文件加载到一个数组中,然后删除第一行:

data = CSV.read("path/to/file.csv")
data = data[1..-1]
但是,这将仅将数据存储为值数组


当您使用
标题:true
时,它使用一个散列,其中键是列标题名。

至于CSV文件的上载和处理,您非常非常接近。您只是在通过
Customer.create读取要填充数据库的数据行时遇到了问题呼叫

看起来您一直在使用只有一行数据的CSV文件进行测试。使用
headers:true
,这一行被转换为标题,随后在
CSV.foreach
迭代器中被忽略。因此,实际上,文件中没有数据,也没有迭代发生。如果输入文件中有两行数据,无论如何,您都会遇到错误

现在,当您使用
headers:false
时,该行数据将被视为数据。这就是问题所在:没有正确处理数据

因为在你的问题中没有模式,我将在字段上假设一点回旋余地;你应该能够很容易地推断,使它在你的情况下工作。此代码显示了它的工作原理:

CSV.parse(csv_data, headers: false) do |row|
  hash = {
    first_name: row[0],
    last_name: row[1],
    age: row[2],
    phone: row[3],
    address: row[4]
  }
  Customer.create!(hash)
end
如果您想要一个带有标题的CSV版本,在这种情况下,这将很好地工作,并且不允许对不应从外部源分配的列进行任意访问:

CSV.parse(csv_data, headers: true, header_converters: :symbol) do |row|
  hash = {
    first_name: row[:first_name],
    surname: row[:last_name],
    birth_year: Date.today - row[:age],
    phone: row[:phone],
    street_address: row[:address]
  }
  Customer.create!(hash)
end
请注意,您的模型中的
Customer#to_csv
也不太正确。首先,它会创建一个带有头的CSV文件,这样您就无法使用此实现导出然后再次导入。接下来,标题字段变量
column\u names
实际上没有在此代码中定义。最后,代码不控制写入CSV的列的顺序,这意味着标题和值可能会不同步。正确的(非标题)版本非常简单:

csv_data = CSV.generate do |csv|
  csv.each do |customer|
    csv << [customer.first_name, customer.last_name, customer.age, customer.phone, customer.address]
  end
end
csv_data=csv.generate do|csv|
csv.每个do |客户|
csv
csv_data = CSV.generate do |csv|
  csv.each do |customer|
    csv << [customer.first_name, customer.last_name, customer.age, customer.phone, customer.address]
  end
end
csv_data = CSV.generate do |csv|
  csv << ["First Name","Last Name","Age","Phone","Address"]
  csv.each do |customer|
    csv << [customer.first_name, customer.last_name, customer.age, customer.phone, customer.address]
  end
end