Rails重复输入' xyz@gmail.com'对于key' index_users_on_email'

时间:2014-06-12 15:54:54

标签: mysql ruby csv ruby-on-rails-4 error-handling

我是Rails的新手,我正在尝试通过CSV将用户上传到我的Rails应用,但是我收到了错误消息。密钥'index_users_on_email'的重复条目'xyz@gmail.com'我不确定如何在CSV中验证重复条目请帮忙。

这是我的代码:

def self.import_students(school, file)

    params = {
      "students_attributes" => {}
    }


    row_count = 1
    users_count = 0
    errors = []

    CSV.foreach(file.path, headers: true) do |row|

      row_count += 1
      standard = Standard.where(name: row["Standard"]).first

      fields = ['Name', 'Email', 'Gender', 'Standard', 'Section']
      fields.each do |field|
        if row[field].blank?
          errors << {
            row: row_count,
            message: "can't be empty",
            column: field
          }
        end
      end
      if standard.blank?
        errors << {
          row: row_count,
          message: "Invalid Standard #{row['Standard']} - Not found",
          column: "Standard"
        }
      end

      section = school.sections.where(standard_id: standard.id, name: row["Section"]).first
      section_id = section.blank? ? nil : section.id
      if section_id.blank?
        errors << {
          row: row_count,
          message: "Invalid Section #{row['Section']} - Not found",
          column: "Section"
        }
      end
      user_params = {
        name: row["Name"],
        email: row["Email"],
        role: User::ROLE_STUDENT,
        gender: row['Gender'].to_s.downcase == "male",
        studies_attributes: {

          "0" => {
            section_id: section_id,
            academic_year_id: school.academic_year.id,
            roll_no: row["Roll"].to_i,
          }
        }
      }
      params['students_attributes'][users_count] = user_params
      users_count += 1

    end

    return {
      params: params,
      errors: errors
    }

  end

我在控制器中的导入操作:

def import
      if params[:students_file].present?
        output = User.import_students(@school, params[:students_file])
      elsif params[:teachers_file].present?
        output = User.import_teachers(@school, params[:teachers_file])
      end


      if output[:errors].blank?
        return output[:params]
      else
        @errors = output[:errors]
        respond_to do |format|
          @action_name = default_action.to_s
          format.html { render action: @action_name }
        end

        return false
      end

    end





 def update
    if (params[:students_file].present?
      output = import
      if output
        build_params = output
      else
        return
      end
    else
      build_params = school_params
    end

    respond_to do |format|
      if @school.update(build_params)
        format.html { default_redirect }
        format.json { head :no_content }
      else
        @action_name = default_action.to_s
        format.html { render action: @action_name }
        format.json { render json: @school.errors, status: :unprocessable_entity }
      end
    end
  end

2 个答案:

答案 0 :(得分:0)

声明一个数组email_count并将email字段存储在email_count中以检查重复的条目。即使我已经添加了for的代码,如果以防电子邮件已经存在于数据库中。

将这段代码添加到您的代码中,在顶部声明 email_count = []

if email_count.include? row["Email"]
  errors << {
    row: row_count,
    message: "Duplicate Entry",
    column: "Email"
  }
end

email_count << row["Email"]

我已更新您的上述代码

def self.import_students(school, file)

    params = {
      "students_attributes" => {}
    }

    email_count = []
    row_count = 1
    users_count = 0
    errors = []

    CSV.foreach(file.path, headers: true) do |row|

      row_count += 1
      standard = Standard.where(name: row["Standard"]).first

      fields = ['Name', 'Email', 'Gender', 'Standard', 'Section']
      fields.each do |field|
        if row[field].blank?
          errors << {
            row: row_count,
            message: "can't be empty",
            column: field
          }
        end
      end
      if User.where(:email => row["Email"]).exists?
        errors << {
          row: row_count,
          message: "Email already taken",
          column: "Email"
        }
      end
      if standard.blank?
        errors << {
          row: row_count,
          message: "Invalid Standard #{row['Standard']} - Not found",
          column: "Standard"
        }
      end

      section = school.sections.where(standard_id: standard.id, name: row["Section"]).first
      section_id = section.blank? ? nil : section.id
      if section_id.blank?
        errors << {
          row: row_count,
          message: "Invalid Section #{row['Section']} - Not found",
          column: "Section"
        }
      end
      # debugger
      if email_count.include? row["Email"]
        errors << {
          row: row_count,
          message: "Duplicate Entry",
          column: "Email"
        }
      end
      email_count << row["Email"]
      # debugger
      user_params = {
        name: row["Name"],
        email: row["Email"],
        role: User::ROLE_STUDENT,
        gender: row['Gender'].to_s.downcase == "male",
        studies_attributes: {

          "0" => {
            section_id: section_id,
            academic_year_id: school.academic_year.id,
            roll_no: row["Roll"].to_i,
          }
        }
      }
      # debugger
      params['students_attributes'][users_count] = user_params
      # debugger
      users_count += 1

    end

    return {
      params: params,
      errors: errors
    }

  end

答案 1 :(得分:-1)

问题不在于您的CSV。听起来问题是你有一个哈希,它试图使用相同的密钥创建两个键值对,在这种情况下是相同的电子邮件地址。您有几个选择:

  1. 要求所有CSV格式的电子邮件都是唯一的
  2. 将密钥从电子邮件更改为真正唯一的密钥,例如user_id或类似的东西
  3. 通过在末尾添加标识符来手动更改重复的电子邮件地址(例如email_1,email_2等)我不推荐这个,但这是您的选择。