委譲の使いどころ

委譲について調べたので記録を残しておきます。

参考

Rubyでdelegation(委譲)を簡単にする2つの方法 http://qiita.com/w650/items/671cc9c49b2ebf60620d

「継承より委譲」≠「継承使うな」 http://osa.hatenablog.com/entry/2014/08/28/204853

まとめ

  • Ruby では Forwardable モジュールを使用することで委譲をより簡単に行うことができる。委譲そのものは Forwardable を使用しなくても実現することができる。
  • 継承と委譲は同じ目的を達成できるがそれぞれにメリット、デメリットが存在する。
  • どんなときにどちらを使うべきかを理解する必要あり。

特異メソッドから直接インスタンスメソッドは呼び出せない

下記のような書き方をするとエラーになる。

class A
  def self.speak
    say_hello 
  end

  def say_hello
    puts "Hello"
  end
end

A.speak # undefined local variable or method というエラーが表示される。

self.speakメソッドの中で自分自身のクラスをnewすると呼び出すことができる。

class A
  def self.speak
    self.new.say_hello
  end

  def say_hello
    puts "Hello"
  end
end

A.speak # Helloと表示される。

エラーになる理由

インスタンスメソッドインスタンスからしか利用できないため。

qrank に新着記事一覧を追加しました

qrank に新着記事を一覧表示するページを追加しました。Qiitaはログインしないと新着記事の一覧を見られないので、多少便利かと思います。

qrank | Qiitaの人気記事ランキング

Rails 4.0.0 でコントローラーに GET リクエストを行うと、何故か複数回コントローラーが実行される

Rails 4.0.0 で特定のコントローラーに GET リクエストを送ると、何故か複数回コントローラーが実行される現象に遭遇しました。しかも直接 URL に GET リクエストを送ると、1度だけ実行されるのですが、HTML の a タグを使って他のページからのリンクで移動するかたちで該当の URL を実行すると複数回実行されるという謎の挙動です。

コントローラーの処理の途中に、ログに文字列を残す処理を書いてログを確認すると複数回分ログに残っていますし、メールを送る処理を書くとメールが複数通数送信されているので、複数回実行されていることは間違いありませんでした。

中の処理の書き方がまずいのかと思っていろいろと変更しても結果に変わりがないため、Rails を最新バージョンの 4.1.5 にアップグレードしたところ、その現象は解消されました。

ターミナルの現在のディレクトリ名や $ が表示される部分(PS1)の色を変えると見やすい

ターミナルで作業をしていると、どの行が自分が実行したコマンドでどの行が標準出力なのか分かりづらかったので、これの色を変えると見やすくなりました。

f:id:suzuki86:20141102173141p:plain

ターミナルの現在のディレクトリ名や $ が表示される部分は PS1 と呼ばれ、PS1 という変数に書式が定義されています。デフォルトで定義されている PS1 に色をつけるだけなら簡単にできました。下記のように .bashrc にて PS1 の値を上書きします。(Ubuntu 14.04で試しました。)

export PS1="\[\e[1;32m\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ \[\e[00m\]"

PS1 の色については下記の記事が参考になりました。
http://babyp.blog55.fc2.com/blog-entry-663.html

追記

tmux を起動した時に反映させるには .bash_profile にも書く必要がありました。

Rails 4 で shared_context を使ったテストを実行すると 「Could not find shared context "hoge"」 というエラーが出るときの対処方法

環境

現象

bundle exec rspec を実行すると、「Could not find shared context "hoge"」 というエラーが表示される。

対処方法

spec_helper.rb の RSpec.configure do |config| の外側に下記を記述することでエラーが出なくなった。

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

なぜ解決されるのかは調査中。

参考

ruby on rails - Rspec - How to include a shared_context in a shared_examples - Stack Overflow