无法获得唯一性validation工作在我正在上传的Excel文件

我的客户端模式有两个属性:: :name:address (这是我们客户网站的url)。 这个应用程序的重点在于查看一个公司是否在呼叫列表或客户端上,然后拨打电话进行查找,以便用户可以input他们的url,看他们是否可以打电话。

我正在使用Ruby 2.3.1和Rails 4.2.6

我有一个唯一性validation以及:addressvalidation设置:address ,但是当我导入一个xlxs文件时,客户端地址已经在数据库中,它仍然上传它们,只是覆盖原来的条目。 同时,如果我不包含地址,则在线validation确实起作用。 如果我以标准Client#newforms逐一添加公司,那么唯一性validation确实起作用。 只是没有与卓越。

我使用这里find的方法: http : //railscasts.com/episodes/396-importing-csv-and-excel?autoplay= true和在这里: https : //github.com/railscasts/396-importing-csv -and-的Excel /树/主/存储与-validation

我正在使用client_import模型和控制器来尝试做这个工作。

这是我的客户端模型:client.rb

 class Client < ActiveRecord::Base #attr_accessible :name, :address validates :address, uniqueness: { case_sensitive: false}, presence: true def self.search(q) where("name LIKE ?", "%#{q}%") where("address LIKE ?", "%#{q}%") end def self.import(file) spreadsheet = open_spreadsheet(file) header = spreadsheet.row(1) (2..spreadsheet.last_row).each do |i| row = Hash[[header, spreadsheet.row(i)].transpose] client = find_by_address(row["address"]) || new client.attributes = row.to_hash #.slice(*accessible_attributes) client.save! end end def self.open_spreadsheet(file) case File.extname(file.original_filename) when ".csv" then Csv.new(file.path, nil, :ignore) when ".xls" then Roo::Excel.new(file.path) when ".xlsx" then Roo::Excelx.new(file.path) else raise "Unknown file type: #{file.original_filename}" end end end 

和我的client_import模型:client_import.rb

 class ClientImport # switch to ActiveModel::Model in Rails 4 extend ActiveModel::Model include ActiveModel::Conversion include ActiveModel::Validations attr_accessor :file def initialize(attributes = {}) attributes.each { |name, value| send("#{name}=", value) } end def persisted? false end def save if imported_clients.map(&:valid?).all? imported_clients.each(&:save!) true else imported_clients.each_with_index do |client, index| client.errors.full_messages.each do |message| errors.add :base, "Row #{index+2}: #{message}" end end false end end def imported_clients @imported_clients ||= load_imported_clients end def load_imported_clients spreadsheet = open_spreadsheet header = spreadsheet.row(1) (2..spreadsheet.last_row).map do |i| row = Hash[[header, spreadsheet.row(i)].transpose] client = Client.find_by_address(row["address"]) || Client.new client.attributes = row.to_hash #.slice(Client.client_import_params) client end end def open_spreadsheet case File.extname(file.original_filename) when ".csv" then Csv.new(file.path, nil, :ignore) when ".xls" then Roo::Excel.new(file.path) when ".xlsx" then Roo::Excelx.new(file.path) else raise "Unknown file type: #{file.original_filename}" end end end 

我的import_clients控制器:client_imports_controller.rb

 class ClientImportsController < ApplicationController def new @client_import = ClientImport.new end def create @client_import = ClientImport.new(params[:client_import]) if @client_import.save redirect_to root_url, notice: "Imported clients successfully." else render :new end end end 

new.html.erb页面的导入窗体:Views / client_imports / newhtml.erb

 <h1>Client Import</h1> <p>A CSV or Excel file can be used to import records. The first row should be the column name. The following columns are allowed.</p> <ul> <% Client.columns.each do |column| %> <% if column.name.in? ["address"] %> <li> <strong><%= column.name %></strong> - <%= column.type.to_s.titleize %> type </li> <% end %> <% end %> </ul> <p>If an <strong>id</strong> is supplied it will update the matching record instead of creating a new one.</p> <%= form_for @client_import do |f| %> <% if @client_import.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@client_import.errors.count, "error") %> prohibited this import from completing:</h2> <ul> <% @client_import.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.file_field :file %> </div> <div class="buttons"><%= f.submit "Import" %></div> <% end %> 

这里是我的路线文件:routes.rb

 Rails.application.routes.draw do resources :clients do collection do get 'search' post 'import' end end resources :client_imports root 'clients#search' end 

我不得不改变模型如何查找预先存在的logging。 我已经设置了寻找类似的地址:

 def load_imported_clients spreadsheet = open_spreadsheet header = spreadsheet.row(1) (2..spreadsheet.last_row).map do |i| row = Hash[[header, spreadsheet.row(i)].transpose] client = Client.find_by_address(row["address"]) || Client.new client.attributes = row.to_hash #.slice(Client.client_import_params) client end end 

但是我需要它像这样通过ID来search

 def load_imported_clients spreadsheet = open_spreadsheet header = spreadsheet.row(1) (2..spreadsheet.last_row).map do |i| row = Hash[[header, spreadsheet.row(i)].transpose] client = Client.find_by_id(row["id"]) || Client.new client.attributes = row.to_hash #.slice(Client.client_import_params) client end end