書いたところで 誰も しあわせにしないコード
まとめ
(この例では有効ではなかったけれど) if...elsif...
が続くコードは、case...when
やループ処理に変換できないか検討してみるといいかもしれない
下の質問に書かれてたコードが気になったので、読んでギョッとする方向性に書き換えてみた
コードの書き換え
質問に書かれてたコード:
if(windows.model1_id.present?) model = Model1.find(windows.model1_id) elsif(windows.model2_id.present?) model = Model2.find(windows.model2_id) elsif(windows.model3_id.present?) model = Model3.find(windows.model3_id) end
書き直してみたコード:
# # モデルとして動作するようテキトーに定義 # module Model1; def self.find(_id); 1; end; end module Model2; def self.find(_id); 1; end; end module Model3; def self.find(_id); 1; end; end class Windows attr_accessor :model1_id, :model2_id, :model3_id end # 検証用にインスタンスを用意 windows = Windows.new windows.model2_id = 12_345 # # ------------------------------- # # # 最終的には Windows インスタンスのプロパティ(名)に対応する、「モデル名で検索」をしたい # ので、対象モデルの検索と呼び出しを可能にするデータ形式を生成する # target_models_range = (1..3) # 各処理については後述 p target_models_range.map { |i| { "Model#{i}": windows.method("model#{i}_id").call.to_s } } .find { |x| x.values.first.size > 0 } .map { |k, v| Kernel.const_get(k).find(v) } .first # 1つ前の map の処理で配列になるので素のデータに直す # => 1 # 実際は検索結果として当該モデルが返ってくる
method()
でオブジェクトが持つメソッド名を文字列ないしシンボルで可変的に指定できるmethod().call(args)
で指定メソッドの呼び出しをする(引数を含めることもできる)- 「最終的に呼び出したいモデル名: (それと対応する)Windows がもつプロパティ値」でハッシュを作る
- プロパティ呼び出しに対して数値を持つ要素を探す(Rails だと
present?
が有用) - 文字列でモデル名を呼び出して その実態に対して find メソッドの呼び出し(Ruby だと
const_get
, Rails だとconstantize
を使う)
Windows モデルに get_model
を生やしてそこに上の処理を置けば、見かけ上解決っていうことにできる...!!
これでModel の数が4 とか5 に増えても対応できるね!ヤッタ!!