Ruby on Rails的:验证CSV文件(Ruby on Rails: Validate CSV

2019-09-28 04:33发布

已经跟随RailsCast上导入CSV( http://railscasts.com/episodes/396-importing-csv-and-excel ),我想验证所上传的文件是一个CSV文件。

我已经使用了宝石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

Answer 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你希望每个模型继承,有其自身的验证来实现。



文章来源: Ruby on Rails: Validate CSV file