在Rails中未成功导入CSV时显示flash



我的Rails应用程序中有一个可用的CSV导入功能。

项目.rb

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

items_controller.rb

def import
  current_user.items.import(params[:file]) 
  flash[:success] = "Import Successful"
  redirect_to spage3_path 
end

这对我来说非常有效。但是,当导入失败时(我对Item模型上的某些字段进行了一些验证),应用程序就会崩溃。在这种情况下,我只想向用户显示一个闪光[:危险]。这就是我修改控制器的方式,但现在每次我都会闪烁[:危险]

items_controller.rb

def import
  if current_user.items.import(params[:file]) 
    flash[:success] = "Import Successful"
    redirect_to spage3_path
  else
    flash[:danger] = "Error Encountered"
    redirect_to spage3_path
  end  
end

请告诉我哪里搞错了。感谢

.create!在对象验证失败时引发异常。您必须处理这种情况以避免应用程序崩溃。您只需在保存之前检查对象是否有效即可。

  • 如果有效:保存并继续分析CSV
  • 如果无效:返回false并停止解析CSV

一个想法可能是:

项目.rb

 #CSV Import Function
 def self.import(file)
   CSV.foreach(file.path, headers: true) do |row|
     item = Item.new(row.to_hash)
     # exit from the block it item is not valid
     return false unless item.valid?
     # save the item only if is valid
     item.save
   end  
 end

使用此方法,您可以保持控制器的原样。

items_controller.rb

def import
  if current_user.items.import(params[:file]) 
    flash[:success] = "Import Successful"
    redirect_to spage3_path
  else # when return false show flash[:danger] to the user
    flash[:danger] = "Error Encountered"
    redirect_to spage3_path
  end  
end

不管实际的错误消息如何,其中一个问题是,当您将import设置为方法时,它是作为实例调用的。

两者之间的区别在于,方法调用该类,而实例的方法在已经调用的类中运行:

#app/models/item.rb
class Item < ActiveRecord::Base
   def self.import
      #class method called by Item.import
   end
   def import
      #instance method called by @item.import
   end
end 

您需要以下内容:

虽然你提到它有效,但我真的认为为current_user.items调用类方法是不好的做法

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :items do
       def import(file)
         CSV.foreach(file.path, headers: true) do |row|
            item = Item.new row.to_hash #-> this might be best as "self.new" to invoke the instance of Item model
            return item.errors unless item.save 
         end  
       end
   end
end

这将使您能够呼叫:

def import
  message = (@file = current_user.items.import(params[:file])) ?  [:notice, "Import Successful"] : [:alert, @file]
  redirect_to.send(spage3_path, "#{message[0]}: #{message[1]}")
end

--

这里有几点需要注意。

首先,我将ActiveRecord Association Extension用于import方法。我这么做是因为你就是这么称呼它的;current_user.items.import

坦率地说,我不知道你当前的设置是如何工作的——如果你调用current_user.items.import——我希望应用程序会恢复错误。您在Item模型的集合上调用import,我希望它只能与实例方法一起使用,而绝对不能与类一起使用。

其次,您必须将异常返回给您的控制器。如果您没有收到任何异常消息,您希望如何调试?我的代码为您提供了返回消息的方式,尽管它可能不正确。

如果存在验证错误,

create!将引发异常。使用create并检查返回值:

def self.import(file)
  CSV.foreach(file.path, headers: true) do |row|
    return :failed unless Item.create(row.to_hash)
  end
end

并将您的控制器更改为:

def import
  if current_user.items.import(params[:file]) == :failed
    flash[:danger] = "Error Encountered"
  else
    flash[:success] = "Import Successful"
  end  
  redirect_to spage3_path
end

最新更新