如何将文件导入 Rails 系统上的 Ruby 而不会收到错误“没有文件或目录 sunch @ rb_sysopen - file.txt
How do I import a file to my Ruby on Rails system without receiving the error "No file or directory sunch @ rb_sysopen - file.txt
我的程序读取一个 .txt 文件,遍历内部信息并将其存储在数据库中。
但是发送文件时出现错误,说它不知道文件路径...据我了解,发送文件时它存储在作为源的变量中,但这没关系.
错误在附加图像中可见。请注意,一条尖线正是未找到的文件将被打开的位置。
但是说他没有找到文件很奇怪,如果在日志中他能够捕获文件并仍然传递文件名...这可能很重要。
控制器
def import
errors = []
file = params['file']
File.open(file).each do |line|
begin
line = line.split("\t")
next if line[0] == "Comprador"
buyer = line[0] rescue row[0]
description = line[1] rescue line[1]
unity_price = line[2].to_f rescue line[2].to_f
quantiti = line[3].to_i rescue line[3] .to_i
address = line[4] rescue line[4]
provider = line[5] rescue line[5]
total_gross = "Total: #{(unity_price * quantiti).round(2)}"
Record.create(buyer: buyer, description: description, unity_price: unity_price, quantiti: quantiti, address: address, provider: provider)
rescue Exception => err
errors << err.message
end
end
if errors.banck?
flash[:success] = "Imported with successful"
else
flash[:error] = errors.join(", ")
end
redirect_to "/file"
查看
<%= form_tag import_path, method: :post do %>
<div class="input-group no-border">
<%= file_field_tag 'file' %>
<%= button_tag 'submit'%>
</div>
<% end %>
程序挂在行“File.open(文件).each do | line |”
我应该怎么做才能停止收到此错误消息?
当您在参数哈希中使用 file_field or file_field_tag in Rails you get an instance of ActionDispatch::Http::UploadedFile 时。这基本上只是一个临时文件实例的包装器。
你甚至不需要首先使用 File.open 并且它会导致错误,因为你在 UploadedFile
实例上隐式调用 #to_s
只是 returns 文件的基本名称。如果你想要路径,你会调用 #to_path
但同样 - 你不需要。
您可以通过调用 #open 打开一个 UploadedFile 实例 (duuh):
def import
params[:file].open do |file|
file.each do |line|
# ...
end
end if params[:file]
end
但除此之外,这段代码确实是无法恢复的错误,并且充斥着诸如 errors.banck?
以及 anti-patterns 之类的内联救援(没有阻塞或异常的救援 class 救援 everything) 和 rescue Exception
这是 Pokémon exception handling 的主要例子。处理异常并不意味着埋葬一切。
从头开始,创建一个单独的服务对象,将文件作为输入并创建(和 returns)您的模型实例。编写覆盖它的测试。然后将其集成到您的控制器中。
这闻起来也很像你 reinventing the CSV wheel。你可以用这样的东西来做:
require 'csv'
# Parses the file as CSV and imports the rows into the database
# Usage `MyImporterService.call(file)`
class MyImporterService
attr_accessor :status, :errors, :results
def initialize(file)
@file = file
@results = []
@errors = []
end
def call
CSV.new(@file, { col_sep: "\t" }).each do |row|
begin
@results << Record.create!(row.slice(:buyer, :description, :unity_price, :quantiti, :address, :provider))
rescue ActiveRecord::RecordInvalid => e
@errors << e.message
end
end
@results
ensure
@file.close
end
# convenience method
def self.call(file)
new(file).tap do |instance|
instance.call
end
end
private
def status
if @results.any? && @errors.none?
:imported_without_errors
elsif @results.any?
:imported_with_errors
elsif @results.none?
:nothing_imported
end
end
def success?
status == :imported_without_errors
end
end
def import
unless params[:file].present?
render :something and return # bail early
end
@import = MyImporterService.call(file)
if @import.success?
redirect to: 'somewhere', success: 'Import went without a hitch'
else
render :something # give the user feedback
end
end
我的程序读取一个 .txt 文件,遍历内部信息并将其存储在数据库中。
但是发送文件时出现错误,说它不知道文件路径...据我了解,发送文件时它存储在作为源的变量中,但这没关系.
错误在附加图像中可见。请注意,一条尖线正是未找到的文件将被打开的位置。
但是说他没有找到文件很奇怪,如果在日志中他能够捕获文件并仍然传递文件名...这可能很重要。
控制器
def import
errors = []
file = params['file']
File.open(file).each do |line|
begin
line = line.split("\t")
next if line[0] == "Comprador"
buyer = line[0] rescue row[0]
description = line[1] rescue line[1]
unity_price = line[2].to_f rescue line[2].to_f
quantiti = line[3].to_i rescue line[3] .to_i
address = line[4] rescue line[4]
provider = line[5] rescue line[5]
total_gross = "Total: #{(unity_price * quantiti).round(2)}"
Record.create(buyer: buyer, description: description, unity_price: unity_price, quantiti: quantiti, address: address, provider: provider)
rescue Exception => err
errors << err.message
end
end
if errors.banck?
flash[:success] = "Imported with successful"
else
flash[:error] = errors.join(", ")
end
redirect_to "/file"
查看
<%= form_tag import_path, method: :post do %>
<div class="input-group no-border">
<%= file_field_tag 'file' %>
<%= button_tag 'submit'%>
</div>
<% end %>
程序挂在行“File.open(文件).each do | line |”
我应该怎么做才能停止收到此错误消息?
当您在参数哈希中使用 file_field or file_field_tag in Rails you get an instance of ActionDispatch::Http::UploadedFile 时。这基本上只是一个临时文件实例的包装器。
你甚至不需要首先使用 File.open 并且它会导致错误,因为你在 UploadedFile
实例上隐式调用 #to_s
只是 returns 文件的基本名称。如果你想要路径,你会调用 #to_path
但同样 - 你不需要。
您可以通过调用 #open 打开一个 UploadedFile 实例 (duuh):
def import
params[:file].open do |file|
file.each do |line|
# ...
end
end if params[:file]
end
但除此之外,这段代码确实是无法恢复的错误,并且充斥着诸如 errors.banck?
以及 anti-patterns 之类的内联救援(没有阻塞或异常的救援 class 救援 everything) 和 rescue Exception
这是 Pokémon exception handling 的主要例子。处理异常并不意味着埋葬一切。
从头开始,创建一个单独的服务对象,将文件作为输入并创建(和 returns)您的模型实例。编写覆盖它的测试。然后将其集成到您的控制器中。
这闻起来也很像你 reinventing the CSV wheel。你可以用这样的东西来做:
require 'csv'
# Parses the file as CSV and imports the rows into the database
# Usage `MyImporterService.call(file)`
class MyImporterService
attr_accessor :status, :errors, :results
def initialize(file)
@file = file
@results = []
@errors = []
end
def call
CSV.new(@file, { col_sep: "\t" }).each do |row|
begin
@results << Record.create!(row.slice(:buyer, :description, :unity_price, :quantiti, :address, :provider))
rescue ActiveRecord::RecordInvalid => e
@errors << e.message
end
end
@results
ensure
@file.close
end
# convenience method
def self.call(file)
new(file).tap do |instance|
instance.call
end
end
private
def status
if @results.any? && @errors.none?
:imported_without_errors
elsif @results.any?
:imported_with_errors
elsif @results.none?
:nothing_imported
end
end
def success?
status == :imported_without_errors
end
end
def import
unless params[:file].present?
render :something and return # bail early
end
@import = MyImporterService.call(file)
if @import.success?
redirect to: 'somewhere', success: 'Import went without a hitch'
else
render :something # give the user feedback
end
end