CSVUP

CSVにデータを入れ、アップすると、入れているデータに基づいて登録が行われる

#StudentController
  
  def upload
    
    begin
      @students,@at_recs = get_data_from_file(params[:file])
     
      if @students.empty?
        render_with_flash("csv_upload","CSVファイルが空か、指定されたファイルが存在しません")
           
      elsif (result = csv_datas_valid?(@students,@at_recs))[0]
     
        new_commer = 0
        for i in 0...@students.size
          unless @students[i].id
            @students[i].save 
            new_commer+=1
          end
          @students[i].attendance_records << @at_recs[i] 
        end
        
        flash[:notice] = "#{@students.size}件のアップロードが完了しました。新規:#{new_commer}件、更新:#{@students.size - new_commer}"
        redirect_to :action => "list"
      else
        render_with_flash("csv_upload",result[1])
      end
      return 
    rescue Exception => e
      render_with_flash("csv_upload","ファイルにエラーがあります。確認して、再度アップロードして下さい:#{e.message}")
    end
  end

  def get_data_from_file(data_stream)
    raise "ファイル形式がCSVではありません" unless data_stream.original_filename =~ /.*\.csv$/
    
    sts = []
    atrs = []
    while(line = data_stream.gets) do
        row = line.chomp.split(/,/)
        raise "1列のサイズは17でなければなりません" unless row.size == Student::CSV_UP_COL_SIZE
        
        student = Student.new_by_csv(row)
        at_rec = AttendanceRecord.new_by_csv(row)
        sts << student
        atrs << at_rec
    end
    return sts,atrs
  end
  
  def csv_datas_valid?(students,at_recs)
    return [false,"学生の数と、出欠データの数が一致していません"] unless students.size == at_recs.size
    
    invalid_lines = []
    for i in 0...students.size
      next if (students[i].valid? && at_recs[i].valid?) 
      invalid_lines << i+1
    end
    return [false,"#{invalid_lines.join(' , ')}行目のデータが不正です。確認して下さい"] unless invalid_lines.empty?
    return [true]
  end
#Student

def to_export_format(event_name)
   result = [ " "+ (event_name == "面接" ? 
                      (self.interview ? self.interview.held_date_time.strftime("%Y/%m/%d") : "") :
                       self.attendance_records.first.event_date.strftime("%Y/%m/%d")  
                    ),
               (event_name == "面接" ? "" : self.attendance_records.first.status.tosjis),
               (self.interview_type ? self.interview_type.name.tosjis : ""),
                self.student_status.name.tosjis,
                self.family_name.tosjis,
                self.first_name.tosjis,
                self.family_name_kana.tosjis,
                self.first_name_kana.tosjis,
                self.sex.tosjis,
                self.mail_address,
                to_mobile_format(self.mobile_phone_no),
              " "+self.birthday.strftime("%Y/%m/%d"),
                self.segment.tosjis,
                self.major.tosjis,
                self.grade,
                self.school.tosjis,
                self.department.tosjis,
                self.apply_channel.tosjis
            ]
    unless self.attendance_records.empty?
      at_rec = self.class.find_by_id(self.id).attendance_records
      return result+["",""] unless at_rec
      
      at_rec_ev_st = at_rec.map{|rec| [rec.event_name,rec.status]}
      result += [(at_rec_ev_st.include?(["説明会","参加"]) ? "".tosjis : "")]
      result += [(at_rec_ev_st.include?(["採裏セミナー","参加"]) ? "".tosjis : "")]
    else
      result += ["",""]
    end
      return result
  end


#AttendanceRecord

  def validate
    return unless self.event_date
    self.errors.add(:event_date,"が現在より先です") if self.event_date > Time.now
  
    unless (EVENT_NAMES.flatten.include?(self.event_name) || self.event_name =~ /面接/)
      self.errors.add(:event_name,"が選択肢にない値です")
    end
    
    unless ATTENDANCE_STATUSES.flatten.include?(self.status) 
      self.errors.add(:status,"が選択肢にない値です")
    end
    
  end

  def self.new_by_csv(row)
    attr ={ 
            :event_date => (row[0] =~ /^\d\d\d\d\/\d\d?\/\d\d?$/ ? Time.parse(row[0]) : ""),
            :event_name => (row[1] ? row[1].toutf8 : ""),
            :status => (row[2] ? row[2].toutf8 : "")
           }
    self.new(attr)
  end
#view

<% @title="CSV一括登録" -%>
  アップロードの雛形を使う場合、事前にヘルプを参照して下さい。<br><br>
  <% form_tag( {:action => "upload"},{ :multipart => true }) do -%>
  <p>アップロードファイル<br>
    <%= file_field_tag(:file) %>
  </p>
  <%= submit_tag("アップロード") %>
  <% end -%>
  <br>
  <%= link_to "戻る",:action => "list" %> 
  <%= link_to "アップロードファイルの雛形","../../user/csv_up_format.csv" %> 
  <%= link_to "一括登録のヘルプ",:action => "csv_upload_help" %>