単純メソッド集

Ruby の基本は DRY ということで,同じことは繰り返さないために,単純な作業でも繰り返しそうなものはメソッドにまとめています.特に,Rails の場合には,以下のように共通なメソッドを書いておく場所が用意されています.

app/controller/application_controller.rb
コントローラで共通なメソッドを書いておける
app/helper/application_helper.rb
ビューで共通なメソッドを書いておける

私の場合は,コントローラでもビューでも使うようなメソッドは lib の下に misc_method.rb として,モジュールを用意しています.昨日の create_delete_check の中でも ncm とかを使ってしまっていました.ということで,多数のメソッドが記載されている中で,システムに依存しないものを抽出して紹介しておきます.

app/controller/application_controller.rb

# vim:set fileencoding=utf-8 filetype=ruby:
class ApplicationController < ActionController::Base
  rescue_from DeviseLdapAuthenticatable::LdapException do |exception|
    render text:exception, status:500
  end
  protect_from_forgery

(中略:ここにはユーザ権限に対応した大量のフィルタが書かれている.CanCan を導入すべきか?)

  # パラメータからオブジェクトを取得する
  # 使い方: @campus, @gakunen, @ids = get_parameters_and_ids [ [ Campus, :id ], [ Gakunen, :gakunen_id ] ]
  def get_parameters_and_ids(parameter_array)
    ans = []
    ids = {}
    parameter_array.each do |pa|
      c, id = pa
      unless params[id] == nil
        ans << c.find(params[id])
        ids[id] = params[id]
      else
        ans << nil
      end
    end
    ans << ids
  end

  # ダウンロード時における IE のファイル名文字化けを回避する
  def IEpatch(fname)
    /MSIE/ =~ request.env['HTTP_USER_AGENT'] ? CGI.escape(fname) : fname
  end

  # excel で出力
  def output_excel(template, fname = nil)
    @excel_page = true
    options = fname ? { filename:IEpatch(fname)} : {}
    send_data(render_to_string(template:template, layout:'excel.html'), options)
  end

  # ロックされていなければ PDF を作成する
  # BatchLock は後日紹介
  def make_pdf_with_lock(fname)
    begin
      BatchLock.run(:output_pdf) do
        yield
        output_pdf fname
      end
    rescue
      processing_pdf fname
    end
  end

  # LaTeX で作成した PDF ファイルを出力する
  # PlatexPdf も後日紹介
  def output_pdf(fname)
    pdf = PlatexPdf::OutputPdfName
    send_file pdf, filename:IEpatch(fname), disposition:'inline'
  end

  # 作業中という PDF ファイルを出力する
  def processing_pdf(fname)
    send_file 'tex/processing.pdf', filename:IEpatch(fname), disposition:'inline'
  end
end

app/helper/application_helper.rb

# vim:set fileencoding=utf-8 filetype=ruby:
module ApplicationHelper

  # 再帰パスを作成
  def recursive_path(ids = {}, option = {})
    request.symbolized_path_parameters.merge(ids).merge(option)
  end

  # key を除いた再帰パスを作成
  def recursive_path_without_key(ids, key)
    ans = request.symbolized_path_parameters.merge(ids)
    ans.delete(key)
    ans
  end

  # excel 書き出しのパスを作成
  def export_excel_path(ids = {}, option = {})
    recursive_path(ids, option.merge(format:'xls'))
  end

  NumberOfSplitTables = 6

  # 長い配列を適当な長さに分割しながら yield する
  def split_yield(array, n = NumberOfSplitTables)
    until ((sub_array = array.slice!(0, n)).length == 0) do
      yield(sub_array)
    end
  end

  # よく使うテーブルヘッダを表示
  def link_title
    render inline:<<-HAML, type: :haml
%tr
  %th リンク
  %th 内容
  %th 権限
HAML
  end

  # date から曜日を得る
  def jweek(date)
    %w(日 月 火 水 木 金 土)[date.wday]
  end

  # date から ○月○日を得る
  def mgdn(date)
    "#{date.month}#{date.day}"
  end

  # date から ○月○日(曜)を得る
  def mgdnw(date)
    "#{mgdn(date)}(#{jweek(date)})"
  end
end

lib/misc_method.rb

# vim:set fileencoding=utf-8 filetype=ruby:

module MiscMethod
  # nil_check.nil の時に別のメッセージを出す
  def nc(o, n = nil)
    o ? o : n
  end

  # nil_check.nil でなければ yield の返値.
  def ncm(o, n = nil)
    o ? yield(o) : n
  end

  # 0 なら表示しない
  def zero_null(o)
    o == 0 ? "" : o
  end

  # array から hash を得る.例: name_hash = array_to_hash(array) { |x| [ x.name, x ] }
  def array_to_hash(array)
    ans = {}
    array.each do |item|
      k, v = yield(item)
      ans[k] = v
    end
    ans
  end

  # array の hash から key に対応した array を得る
  def array_from_hash_array(hash_array, key)
    hash_array[key] ||= []
  end

  # array から array の hash を得る
  def array_to_hash_array(array)
    ans = {}
    array.each do |item|
      k, v = yield(item)
      array_from_hash_array(ans, k) << v
    end
    ans
  end

  # hash の hash から key に対応した hash を得る
  def hash_from_hash_hash(hash_hash, key)
    hash = hash_hash[key] || hash_hash[key] = {}
  end

  # hash の hash に オブジェクトを挿入する
  def set_object_to_hash_hash(hash_hash, object, key1, key2)
    hash = hash_from_hash_hash(hash_hash, key1)
    hash[key2] = object
  end

  # array の hash の hash にオブジェクトを挿入する
  def set_object_to_hash_hash_array(hash_hash_array, object, key1, key2)
    hash_array = hash_from_hash_hash(hash_hash_array, key1)
    array = array_from_hash_array(hash_array, key2)
    array << object
  end

  # 配列の内容を累計
  def array_sum(array)
    ans = 0
    array.each do |n|
      ans += n if n.class == Fixnum
    end
    ans
  end

  # 小数点以下 2 位を四捨五入する (format "%4.1f", 8.45 などでは正しく四捨五入されないため)
  def round1(num)
    (num * 10).round / 10.0
  end

  # flag から ○×を得る
  def mb_options_for_select
    [ [ '', true ], [ '×', false ] ]
  end

  # flag から ○×を得る
  def mb(flag)
    flag ? '' : '×'
  end

  # flag から ○を得る
  def mn(flag)
    flag ? '' : ''
  end
end

用途が多岐にわたっており,細かく説明することができなくてすみません.また関連するネタが出たらそこで説明できればと思います.