Meadow設定
・インストール
http://www.meadowy.org/meadow/wiki/%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89
3.00のjaをゲット。パッケージは全てインストールした。
・半透明化
http://www.meadowy.org/meadow/wiki/%E8%A9%B3%E7%B4%B0%E8%A8%AD%E5%AE%9A%E5%8F%8A%E3%81%B3%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD
インストールの際に、.emacsの参照場所を、何もいじっていない。
その上で、C:\meadow\.emacsを自分で作成。あとは、コードを書いた
・Rubyに対応
http://capsctrl.que.jp/kdmsnr/?Meadow#l18
miscを検索。あとは、これにのっている通り。
できた〜☆
あと、RHTMLとかにも対応させたいよね。
http://hp.vector.co.jp/authors/VA021626/pc/meadow.html#HTML
入力文章からの改行の反映
#in helper def h_with_br(text) safe_text = h(text) #一度サニタイズ safe_text.gsub(/\n/,"\n<br>")#\nはソース上でも改行するために end
※gsub!を使うと上手く行かないので注意。
gsub!はマッチしなかった時に、元の文字列でなくnilを返してしまうから。よって、
gsubを用いる。結構はまります。
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" %>
既存のクラスを拡張してメソッドを持たせる
■テストの際にも使える(例:ファイルアップのテスト)
ファイルアップは、multipartフォームが用いられ、malutipart/form-dataで扱われるオブジェクト
は、StringIO(大きいとFileになる?)であり、かつ、以下の3つのメソを持っている。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
・local_path
・original_filename
・content_type
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
しかし、テストでFileオブジェクトを生成して、
post :upload :file => File.open(filename)のようにやっても、例えば、コントローラの方で、
params[:file].original_filenameとかの操作を行っていたらならば、当然、UndefMethodエラー
となる。
これを防止するために、IOを持つFileクラスのオブジェクトに、上記の3つのメソッドを追加して、
あたかもmultipartで送られてきたデータのように振舞わせる。
今回は、original_filenameだけを持たせてみる。
def upload_file(filename) t = File.open(filename,"r") (class << t; self; end).class_eval do define_method(:original_filename){File.basename(filename)} end return t end
このように、クラスのファイルに書くのではなく、オブジェクトを生成してから書いている。
※オリジナルはこれ
http://wiki.rubyonrails.org/rails/pages/HowtoUploadFiles
または、「はじめようRuby on Raiks」p116
これを使ったCSVUPのテストはこんな感じ
def test_upload previous_count = Student.count post :upload,:file => upload_file(File.dirname(__FILE__) + '/../../upload_files/test_upload.csv') assert_redirected_to :action => "list" assert_equal 2,assigns(:students).size assert_equal assigns(:students).size,assigns(:at_recs).size assert_equal previous_count + 2,Student.count end def upload_invalid_test(filename) previous_count = Student.count post :upload,:file => upload_file(File.dirname(__FILE__) + '/../../upload_files/' + filename) assert_template "csv_upload" assert_equal previous_count ,Student.count end def test_invalid_upload_with_invalid_filetype upload_invalid_test('test_upload.xls') end def test_invalid_upload_with_over_linesized_file upload_invalid_test('test_overline_upload.csv') end def test_invalid_upload_with_invalid_params upload_invalid_test('test_invalid_upload.csv') end