Ruby csv upload不会在Database中显示记录

时间:2017-06-28 09:53:24

标签: ruby-on-rails csv

我有一个功能性的ruby应用程序,我是通过跟踪基础架构教程创建的,很少或没有fus,我尝试按照tutorial将多个记录上传到数据库中。 它似乎非常直接,并认为我可以在几分钟内完成它。

问题是当我上传csv文件时,我收到上传成功的通知,首先,只创建一条记录,其次创建的记录为空。

我已经搜索和搜索过,尝试过其他教程并最终遇到同样的问题......我基本上都是在智慧结束。请参阅下面的代码片段:

hospital.rb

class Hospital < ApplicationRecord
  mount_uploader :image, ImageUploader

  searchkick

  has_many :reviews

  #validates :name, :address, :phone, :image, presence: true
  #validates :website, format: { with: /\Ahttps?:\/\/.*\z/,
  #message: "must start with http:// or https://" }
  #validates :phone, numericality: {
  #only_integer: true,
  #message: "must be land line(7 digits) or Gsm(11 digits)"
  #}
end

hospital_controller.rb

class HospitalsController < ApplicationController

  ...

    def import
      Hospital.import(params[:file])
    end

  ...

    def create

      @hospital = Hospital.new(hospital_params)

      respond_to do |format|
        if @hospital.save
          format.html { redirect_to @hospital, notice: 'Hospital was successfully created.' }
          format.json { render :show, status: :created, location: @hospital }
        else
          format.html { render :new }
          format.json { render json: @hospital.errors, status: :unprocessable_entity }
        end
      end

    end

  private

    def hospital_params
      params.require(:hospital).permit(:name, :address, :city_town, :state, :phone, :website, :safe_care, :jci, :cohsasa, :best_known_4, :image )
    end

end

Rails服务器上的输出

 Started POST "/hospitals" for ::1 at 2017-06-22 12:58:09 +0100
 Processing by HospitalsController#create as HTML
 Parameters: {"utf8"=>"✓", 


 "authenticity_token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx==", 
  "hospital"=>{"name"=>"", 
 "address"=>"", "city_town"=>"", "state"=>"", "phone"=>"", "website"=>"", 
 "safe_care"=>"", "jci"=>"", "cohsasa"=>"", "best_known_4"=>""}, "file"=>#
 <ActionDispatch::Http::UploadedFile:0x007fe064b78918 @tempfile=#


 <Tempfile:/var/folders/xh/hv6bwdzs3cx4ws9x42n3gsn00000gn/
 T/RackMultipart20170622-80750-147ctbc.csv>, @original_filename="Test.csv", 
 @content_type="text/csv", @headers="Content-Disposition: form-data; 
 name=\"file\"; filename=\"Test.csv\"\r\nContent-Type: text/csv\r\n">, 
 "commit"=>"Import CSV"}
 User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? 
 ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
 Can't verify CSRF token authenticity.
(0.1ms)  begin transaction
(0.1ms)  commit transaction
(0.1ms)  begin transaction
SQL (0.5ms)  INSERT INTO "hospitals" ("name", "address", "phone", "website", 
"created_at", "updated_at", "city_town", "state", "jci", "cohsasa", 
"best_known_4", "safe_care") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  
[["name", ""], ["address", ""], ["phone", ""], ["website", ""], ["created_at", 
2017-06-22 11:58:09 UTC], ["updated_at", 2017-06-22 11:58:09 UTC], 
["city_town", ""], ["state", ""], ["jci", ""], ["cohsasa", ""], 
["best_known_4", ""], ["safe_care", ""]]
(0.8ms)  commit transaction
Hospital Store (170.8ms)  {"id":53}
Redirected to http://localhost:3000/hospitals/53
Completed 302 Found in 188ms (Searchkick: 170.8ms | ActiveRecord: 1.9ms)

2 个答案:

答案 0 :(得分:0)

在模型中尝试下面的代码来导入csv ini db并在控制器中调用它:

def self.import(file)
      spreadsheet = open_spreadsheet(file)
      header = spreadsheet.row(2)
      (3..spreadsheet.last_row).each do |i|
        row = spreadsheet.row(i) #Hash[[header, spreadsheet.row(i)].transpose]
        f1= from = row[0]
        f2 = row[1]
        f3 = row[2]


        ModelName.create({f1: f1, ... })
      end
end

答案 1 :(得分:0)

您的代码的行为完全按照您的行为编写:

  

首先,只创建一条记录 ...

是的。因为你从不打电话:

Hospital.import(params[:file])

这是在import行动中,但您从未通过create行动拨打电话。当教程说:

  

步骤:3

     

在控制器中添加块

这并不意味着“你喜欢任何旧地方,它会被神奇地称为”。你必须实际调用逻辑。但是,你没有。所以你的应用程序对CSV文件没有任何作用。这正是您告诉它与CSV文件有关的内容。

(另外,你的Hospital类没有导入类方法。所以,当你最终调用它时,它会抛出一个错误。)

  

其次,创建的记录为空...

再次。正如你写的那样。

正如您在控制台中看到的那样,您的医院参数是空的:

Started POST "/hospitals" for ::1 at 2017-06-22 12:58:09 +0100
Processing by HospitalsController#create as HTML
Parameters: {
  "utf8"=>"✓", 
  "authenticity_token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx==",
  "hospital"=>{
    "name"=>"", 
    "address"=>"", 
    "city_town"=>"", 
    "state"=>"", 
    "phone"=>"", 
    "website"=>"", 
    "safe_care"=>"", 
    "jci"=>"", 
    "cohsasa"=>"", 
    "best_known_4"=>""
  },
  "file"=>#<ActionDispatch::Http::UploadedFile:0x007fe064b78918 @tempfile=#

所以,当你这样做时:

  @hospital = Hospital.new(hospital_params)

然后:

  if @hospital.save
    ...
  else
    ...
  end

嗯,你刚刚告诉你的应用程序创建了一个空白记录,并且它很快就符合要求(特别是因为你已经删除了所有的验证)。

所以...编写Hospital.import方法(参见教程的第4步),如下所示:

  class Hospital < ApplicationRecord

    mount_uploader :image, ImageUploader

    searchkick

    has_many :reviews

    #validates :name, :address, :phone, :image, presence: true
    #validates :website, format: { with: /\Ahttps?:\/\/.*\z/,
    #message: "must start with http:// or https://" }
    #validates :phone, numericality: {
    #only_integer: true,
    #message: "must be land line(7 digits) or Gsm(11 digits)"
    #}

    def self.import(file)
      CSV.foreach(file.path, headers: true) do |row|
        Hospital.create! row.to_hash
      end
    end

  end

在您的控制器中调用它,例如:

    def create

      import if params[:file] # <= this here is the call to your import method

      @hospital = Hospital.new(hospital_params)

      respond_to do |format|
        if @hospital.save
          format.html { redirect_to @hospital, notice: 'Hospital was successfully created.' }
          format.json { render :show, status: :created, location: @hospital }
        else
          format.html { render :new }
          format.json { render json: @hospital.errors, status: :unprocessable_entity }
        end
      end

    end

重新添加您的验证。您将在途中更接近。