【问题标题】:Ruby on Rails: Validate CSV fileRuby on Rails:验证 CSV 文件
【发布时间】:2016-12-15 20:08:47
【问题描述】:

按照 RailsCast 导入 CSV (http://railscasts.com/episodes/396-importing-csv-and-excel),我正在尝试验证正在上传的文件是 CSV 文件。

我已使用 gem csv_validator 来执行此操作,如此处所述 https://github.com/mattfordham/csv_validator

所以我的模型看起来像这样:

class Contact < ActiveRecord::Base
  belongs_to :user

  attr_accessor :my_csv_file
  validates :my_csv_file, :csv => true

  def self.to_csv(options = {})
    CSV.generate(options) do |csv|
        csv << column_names
        all.each do |contact|
            csv << contact.attributes.values_at(*column_names)
        end
    end
  end
    def self.import(file, user)
    allowed_attributes = ["firstname","surname","email","user_id","created_at","updated_at", "title"]
    CSV.foreach(file.path, headers: true) do |row|
        contact = find_by_email_and_user_id(row["email"], user) || new
        contact.user_id = user
        contact.attributes = row.to_hash.select { |k,v| allowed_attributes.include? k }
        contact.save!
    end
  end
end

但我的系统仍然允许我选择导入非 CSV 文件(例如 .xls),我收到错误消息:invalid byte sequence in UTF-8

谁能告诉我为什么以及如何解决这个问题?

请注意,我使用的是 Rails 4.2.6

【问题讨论】:

  • 您可以在尝试导入文件之前检查文件的扩展名:file.path.split('.').last.to_s.downcase == 'csv'
  • @MrYoshiji 感谢您的评论,不过我也想验证某些列中的数据,这个 gem(应该)允许我这样做
  • 此 gem 允许您检索列中的数据,您负责制定逻辑以“验证列中的数据”。如果您想要一些关于从哪里开始的提示,我可以发布答案
  • 好的,能不能请您回复一下

标签: ruby-on-rails ruby excel csv ruby-on-rails-4


【解决方案1】:

你可以创建一个新类,比如说ContactCsvRowValidator

class ContactCsvRowValidator

  def initialize(row)
    @row = row.with_indifferent_access # allows you to use either row[:a] and row['a']
    @errors = []
  end

  def validate_fields
    if @row['firstname'].blank?
      @errors << 'Firstname cannot be empty'
    end

    # etc.
  end

  def errors
    @errors.join('. ')
  end
end

然后像这样使用它:

# contact.rb
def self.import(file, user)
  allowed_attributes = ["firstname","surname","email","user_id","created_at","updated_at", "title"]
  if file.path.split('.').last.to_s.downcase != 'csv'
    some_method_which_handle_the_fact_the_file_is_not_csv!
  end
  CSV.foreach(file.path, headers: true) do |row|
    row_validator = ContactCsvRowValidator.new(row)
    errors = row_validator.errors
    if errors.present?
      some_method_to_handle_invaid_row!(row)
      return
    end

    # other logic
  end
end

可以轻松修改此模式以满足您的需求。例如,如果您需要在几个不同的模型上进行导入,您可以创建一个基本的 CsvRowValidator 来提供诸如validate_fieldsinitializeerrors 等基本方法。然后,您可以为所需的每个模型创建一个继承自该 CsvRowValidator 的类,并实现其自己的验证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 2014-12-04
    • 2011-05-09
    • 2011-07-04
    • 2016-08-04
    相关资源
    最近更新 更多