无法使用Ruby on Rails导入.csv文件

时间:2018-07-23 10:06:36

标签: ruby-on-rails ruby csv

我正在尝试从.csv文件导入产品列表,但无法将csv文件中的数据导入MySQL数据库。在csv产品文件上,有7列,分别是产品代码说明尺寸(Please click to see the expample)来自表Product本身。其他列来自其他表格,分别是颜色类别代码供应商单位。我的问题是,它会在“产品代码”字段中不断插入“ CSV导入07/23/2018 05:06 PM ”(或任何时间/日期)。它应该是CSV文件中的产品代码值(例如100778)。但该消息表明它已成功(here)导入,但数据库上没有任何变化。您认为这里的问题是什么?


这是我的模特:

product.rb:

class Product < ApplicationRecord
  require 'csv'
  belongs_to :category, optional:true
  belongs_to :supplier, optional:true
  belongs_to :color, optional:true
  belongs_to :unit, optional:true
  accepts_nested_attributes_for :serial, allow_destroy: true

  validates :product_code, presence: true, uniqueness: true

   def import file
      status = true
      message = ""
      last_location = ""
      color_id, unit_id, category_id, supplier_id = ""

      index = 2
        CSV.foreach(file.path, headers: true) do |row|
            if row["Product Code"].nil? || row["Product Code"].blank?
                  status = false
                  message = "Error: Product Code is required on row #{index}."
                break
            elsif row["Category Code"].nil? || row["Category Code"].blank?
                  status = false
                  message = "Error: Category Code is required on row #{index}."
                break
            elsif row["Supplier"].nil? || row["Supplier"].blank?
                  status = false
                  message = "Error: Supplier is required on row #{index}."
                break
            elsif row["Unit"].nil? || row["Unit"].blank?
                  status = false
                  message = "Error: Supplier is required on row #{index}."
                break
            else
              stock_no = row["Product Code"].to_s.downcase.strip
              product = Product.where("LOWER(product_code) = '#{stock_no}'").first
              if product.nil?
                  status = false
                  message = "Error: No matching item #{stock_no} on row #{index}."
                break
              end
              color_name = row["Color"].to_s.downcase.strip
              color = Color.where("LOWER(name) = '#{color_name}'").first
              if color.nil?
                  status = false
                  message = "Error: No matching color #{color_name} on row #{index}."
                break
              end 
              category_name = row["Category Code"].to_s.downcase.strip
              category = Category.where("LOWER(name) = '#{category_name}'").first
              if category.nil?
               status = false
               message = "Error: No matching category #{category_name} on row #{index}."
               break
             end
             supplier_name = row["Supplier"].to_s.downcase.strip
                  supplier = Supplier.where("LOWER(name) = '#{supplier_name}'").first
              if supplier.nil?
                  status = false
                  message = "Error: No matching supplier #{supplier_name} on row #{index}."
                break
              end

                  unit_name = row["Unit"].to_s.downcase.strip
                  unit = Unit.where("LOWER(name) = '#{unit_name}'").first
              if unit.nil?
                  status = false
                  message = "Error: No matching unit on row #{index}."
                break
              end

            end
          index += 1
          last_location = row["Location"]
      end 
      if status
        imported = 0

          color = Color.where(["LOWER(name) = ?", 'row[color]'.downcase]).first
          color_id = color.nil? ? nil : color.id

          unit = Unit.where(["LOWER(name) = ?", 'row[unit]'.downcase]).first
          unit_id = unit.nil? ? nil : unit.id

          category = Category.where(["LOWER(name) = ?", 'row[category]'.downcase]).first
          category_id = category.nil? ? nil : category.id

          supplier = Supplier.where(["LOWER(name) = ?", 'row[supplier]'.downcase]).first
          supplier_id = supplier.nil? ? nil : supplier.id


          product = Product.new product_code: "CSV Import #{Time.zone.now.strftime('%m/%d/%Y %I:%M %p')}", color_id: color_id, category_id: category_id, supplier_id: supplier_id, unit_id: unit_id
        if product.save
            CSV.foreach(file.path, headers: true) do |row|
              product = Product.where(["LOWER(product_code) = ?", row["Product Code"].downcase]).first
              unless product.nil?
                 product = Product.new product_code: product.id, color: color_id.id, category_id: category_id, supplier_id: supplier_id, unit_id: unit_id
                if product.save
                  imported += 1
                end
        end 
     end 
    message = "#{imported} record(s) have been imported successfully."
   end
  end
     return [status, message]

 end
end

products_controller.rb:

class ProductsController < ApplicationController
  def create
   @product = Product.new(product_params)
    if params[:todo] == "import"
     import = Product.import params[:product][:file]
     session[:import_flash] = import[1] 
      if import[0]
        redirect_to import_product_path
      else
        redirect_to import_product_path
      end
    else
      @product = Product.new(product_params)
    if @product.save
      redirect_to products_path, notice: "Product created successfully."
    else
     flash.now[:error] = "#{@product.errors.full_messages.first}."
      render :new
    end
  end
 end

  def product_params
    params.require(:product).permit(
    :product_code, :description, :size, :barcode, :color_id, :unit_id, :category_id, :supplier_id, :qty, :price, 
    :serial_attributes => [:id, :serial_no, :power, :serial_type, :cyl, :product_id,:_destroy]
  )
  end

end

import_product_csv.js:

function validateProductCSV(param) {
 if (param == "product") {
  var file = document.getElementById("product_file");
 } 
 else {
  var file = document.getElementById("product_file");
 }

 p_error = document.getElementById("p_error");
 no_errors = true;
 err_mes = "";

 if (file.value == "") {
 no_errors = false;
 err_mes = "CSV file is required.";
 }

 ext = file.value.split('.').pop();
 if ((ext != "csv" && ext != "CSV") && no_errors) {
 no_errors = false;
 err_mes = "Selected file is not a valid CSV.";
 }

 if (no_errors) {
  return true;
 } 
 else {
  p_error.innerHTML = err_mes;
  file.focus();
  return false;
 }
}

视图: import.html.erb:

<%= form_for Product.new do |f| %>
 <div class="header">
 <h4 class="title"> <%= link_to "Products", products_path %> / Import 
 <%= f.submit "Import", class:"btn btn-flat btn-flat pull-right", data:{disable_with:"Importing.."}, style:"color:#000000;", onclick: "return validateProductCSV('product');" %></h4>
 </div>
<br><br>
<%= render "form_import", f:f %>
<% end %>

(表单) _form_import.html.erb:

<%= javascript_include_tag "import_product_csv" %>
 <div class="content">
  <div class="container-fluid">
   <div class="row">
    <div class="col-md-12">
     <div class="card">
      <div class="card-content">
        <div class="content">
          <div class="row">
            <div class="col-md-12">
              <p style="font-family:'Calibri'; font-size:12pt; color:red; font-weight:bold; padding-left:15px;" id="p_error"><%= session[:import_flash] %></p>
              <% session[:import_flash] = nil %>
              <div class="box box-primary">
                <div class="box-body">
                  <div class="form-group">
                    <div class="col-md-4">
                      <%= f.label :name, "Choose a CSV file" %>
                      <%= f.file_field :file, class:'form-control' %>
                      <input type="hidden" name="todo" value="import">
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

1 个答案:

答案 0 :(得分:0)

您正在此行中将product_code设置为“ CSV导入...”

product = Product.new product_code: "CSV Import #{Time.zone.now.strftime('%m/%d/%Y %I:%M %p')}", color_id: color_id, category_id: category_id, supplier_id: supplier_id, unit_id: unit_id

您应该更改此位

product_code: row["Product Code"].to_s.downcase.strip

我不明白这部分的目的

if product.save
        CSV.foreach(file.path, headers: true) do |row|
          product = Product.where(["LOWER(product_code) = ?", row["Product Code"].downcase]).first
          unless product.nil?
             product = Product.new product_code: product.id, color: color_id.id, category_id: category_id, supplier_id: supplier_id, unit_id: unit_id
            if product.save
              imported += 1
            end
    end

在方法开始时,我将import =设置为0,然后执行

    if product.save
      imported += 1
    end