Hatena::ブログ(Diary)

杉風呂2.0 - A Lifelog -

2015-12-01(火)

else に書かれるべきロジック

2 種類が混ざって使われていないか?という気づきをメモしておく。

  • 正常系パス
    • 例えば、boolean を返す問い合わせメソッドのように 分岐のコードパスが 2 つしかない場合
    • これは何も問題ない
  • 例外を避けて安全側に倒したデフォルト
    • これが正常系パスのように扱われているケースがないか?
    • ほんとに後続処理をして問題ないか?
    • 例外を出せない理由があるなら、ログを追加して運用で対処したりすべきではないか?(と考えているが、そのように判断されることがないように思うのでこの記事をメモした次第。)

2012-06-18(月)

[][]Rails for Beginners Vol.0 にサポートとして参加しました。

Rails for Biginners Vol.0 (ビギナー枠) にサポートエンジニアとして参加させてもらい、ついでに Rails 3 本ソムリエなトークをしました。

Rails for Beginners Vol.0 (ビギナー枠)

http://atnd.org/events/28948

松本瞬さんによる初の試みでしたが、参加枠 10 人に対し、18 人の申し込みがあり、全員の参加が無理だったものの、プログラマではないけど意欲があるという方も参加されていてよかったなと思います。

当日何をやるかについて、主催者は、

というわけで半ば丸投げwでした。

環境構築組のサポートということで、僕とペアを組まれた方は、HTML などを少しづつ学んでいる方ということで、説明などは割とアバウトな感じで。3〜4時間しかない一日イベントでしたし。

エラーメッセージを見ると、

  • Rails Installer は /private/etc/profile の権限に 0440 を要求していたが、 0666 になっていた。(理由は不明)

/private/etc/profile というのは、 /etc/profile と i ノード番号が同じだったので、ハードリンクのようですね。

それはさておき、権限を変更することに。ちなみに、隣の主催者ペアは rvm や gem でインストールする作戦に切り替えた模様。

その際に、ターミナルの操作にそれほど慣れていないということだったので、

  • ls -ltr コマンド
  • Ctrl + P と Ctrl + N でターミナルの履歴を行き来できること

などといった小ネタをはさみつつ、僕も忘れていたのだが、Macデフォルトでは su コマンド使えないので、

を説明し、ちょっとビビリつつ、

  • passwd rootroot パスワードを設定
  • chmod コマンド で 0440 に設定

という作業をして、再度インストールに挑戦。

ちなみに、LinuxMac OS などの UNIX 系 OS の入門には『UNIX先生』をオススメしています。表紙はかなりあやしげですが。

UNIX先生

UNIX先生

インストールを待つ間、僕の方の PC を使って説明。

当日は、家にある Rails 3の日本語書籍を大量に持ち込んでいたので、次の本を参考に進めました。重かった。

  • rails newコマンド
  • rails new したときに最後に bundle install が走ること
  • rails serverコマンド
  • WEBRick が簡易Webサーバであること
  • アクセスしたときログに出るステータスコード200の意味。Ctrl + C で停止できること
  • RDBMSExcel のようなものであること(笑)、デフォルトSQLite を使うこと
  • RailsMVC やテーブルやモデル、コントローラの命名規則
  • MVC フレームワークについて、パーツ分割するという程度のこと
  • rails generate saffold
  • rake db:migrate
  • マイグレーションファイルについて、ターゲットDBMSの型と Rails での表現がマッピングされているということ
  • rake db:rollback
  • rails dbconsole で マイグレーションファイルの日付が schema_migrations テーブルに挿入されていること、rake db:rollback 時に実際にテーブルが削除されること(教えていて、あらためて気づきましたが、マイグレーションファイルの日付ってlocale の時刻じゃないんですね。)
  • ブックマークアプリ画面から入力後、rails console で、Bookmark.all 、 Bookmark.first 、 Bookmark.last 、Bookmark.where(name: => "hoge")を試す

rails console を試した理由を尋ねられ、一瞬固まってしまいましたが、

  • SQLについては、そういうデータベース問合せ言語がありますよという程度
  • MVCのファイルの配置とマッピングの命名規則、コントローラの@bookmarks に Bookmark.all が格納されること、それがビューに渡ってくるところ
  • scaffold のURLとコントローラのメソッドhtml.erbファイルと対応
  • URLの対応をroutes.rb で定義していること
  • Asset Pipeline について、SCSSが上手く説明できなかった(要復習w)

このあたりは、 Minami.rb のスライドなどを予習してきてもらえればよかったなと、あとで気づきました。次回移行の課題ですかね。

Rails初心者レッスン lesson1

http://www.slideshare.net/satomicchy/rails-lesson1

終盤は、環境構築組で是非ということで、heroku にアップロードをやりました。

Gemfile については『基礎Ruby on Rails』で軽く触れられています。bundle install とbundle update の違いを知らない方はご一読を。このあたりも僕がこの本を薦める理由です。

改訂新版 基礎Ruby on Rails (IMPRESS KISO SERIES)

改訂新版 基礎Ruby on Rails (IMPRESS KISO SERIES)

残念なことに、git init する前に、 heroku create をしてしまい、作業をやり直していてタイプアップとなりました。この辺りは僕の課題として、よく素振りしておきたいところです。Heroku で自分が作ったものが Web に公開されるのは、とてもインパクトがあるようですね。

git はほんとの最初の一歩としてならドットインストールをオススメします。かくいう僕も git 弱者で現在学習中です。

gitの基礎 - ドットインストール

dotinstall.com/lessons/basic_git

終了後に番外編として、日本語で書かれた Rails 3 本をすべて紹介するミニトークをしました。これについては、独断と偏見による身勝手トークなので、参加者のみの特典ということにしておこうかと。トークで触れませんでしたが、英語にアレルギーがなければ、Rails Tutorial もオススメです。最近 3.2 対応に改訂されていて、有料版のScreecast は RSpec を使ったTDDテスト駆動開発)を学ぶのに最高の教材です。周辺ツールも一番使っていますしね。たまに Railscasts のようなボーナストラックが送られてきたりします。

Rails Tutorial

http://ruby.railstutorial.org/

僕自身も勉強になったし、いい刺激にもなり、面白い時間でした。OmniAuth やAamazon S3 やってたテーブルの話も聞いてみたかったなぁ。

最後にお役立ちな小ネタを 1 つ。

2012-06-05(火)

[][]Rails で十分に活用されていなくてもったいない ActiveRecord::Relation のメソッド TOP 10

2013年12月2日更新: 参照されることが多いので Rails 4 の情報を訳注として追記しました。また、Rails 4 に関する情報は、 WEB+DB PRESS Vol.73 が非常に参考になるので、一読をおすすめします。

この文章は Mitch Crowe 氏のブログより 2012年4月14日の記事を翻訳したものです。


The 10 Most Underused ActiveRecord::Relation Methods

http://blog.mitchcrowe.com/blog/2012/04/14/10-most-underused-activerecord-relation-methods/


昨日は ActiveRecord::Relation のコードに膝まで浸かって、使われているのをこれまで全然見たことがない面白いナゲットを思い出させてくれた。この記事で、十分に活用されていない Relation クラスのメソッドのトップ10をリストにしたので、楽しんでもらいたい。

10位 ブロック付きの first_or_create

first_or_create はとてもなじみ深い。

Book.where(:title => 'Tale of Two Cities').first_or_create

そして、名前通りのことをやってくれる。だが、特定の属性を持つレコードを find するとか、それらの属性を持つレコードを create して、さらに追加で属性を設定したくなることが頻繁にあると思う。これを簡潔にやるには first_or_create にブロックを与えればいい。

Book.where(:title => 'Tale of Two Cities').first_or_create do |book|
  book.author = 'Charles Dickens'
  book.published_year = 1859
end

9位 first_or_initialize

このレコードをまだ保存したくない場合は、 first_or_initialize が使える。

Book.where(:title => 'Tale of Two Cities').first_or_initialize

8位 scoped

あるクラスの持つすべてのレコードを表した ActiveRecord::Relation がほしいことがある。そんなときは scoped メソッドを使えば簡単に生成できる。(訳注: Rails 4 では、 scoped が非推奨になり、 all が Array から ActiveRecord::Relation のオブジェクトを返すようになりました。Rails 4 では scoped から all に変更してください。)

def search(query)
  if query.blank?
    scoped
  else
    q = "%#{query}%"
    where("title like ? or author like ?", q, q)
  end
end

7位 none ( Rails 4 のみ)

同じように、オブジェクトを含まない ActiveRecord::Relation がほしいことがある。空の Array を返すことが、大抵それほどよくないのは、 API の利用者が Relation オブジェクトを期待しているからだ。代わりに none を使えばいい。

def filter(filter_name)
  case filter_name
  when :all
    scoped
  when :published
    where(:published => true)
  when :unpublished
    where(:published => false)
  else
    none
  end
end

注意:最先端を行く人は今すぐ none を使いたくなっていることだと思う。これは、 Rails 3 ではなく、 Rails 4 で利用できる。だが、Rails 4 を待つまでの間も簡単に書くことができる。 この Stack Overflow のスレッドをチェックしてほしい。

6位 find_each

数千レコードをイレテートさせたくなっ場合、each を使いたくはないだろう。

each は1 つのクエリを実行して、全レコードを取得し、それらすべてをメモリ上にインスタンス化してしまう。メモリを十分に確保しているならいい。確保してなければ、これは Rails アプリをフリーズさせる素敵な方法になる。find_each は、そうではなく、レコードをバッチ処理で find して(デフォルトは1000件)、一度に yield する。その結果、同時に全レコード分のメモリを確保する必要がなくなる。

find_each は yield されるレコードの順序を指定できないので注意だ。指定してもただ単に無視される。

Book.where(:published => true).find_each do |book|
  puts "Do something with #{book.title} here!"
end

5位 to_sql と explain

ActiveRecord は素晴らしいが、思った通りのクエリをいつも生成してくれるとは限らない。コンソールに飛んで、組み立てた Relation で この 2 つの命令を実行してみよう。賢いクエリにマップされているか確認して、そうなってなかったら愛情込めて作ったインデックスを使うようにしよう。

Library.joins(:book).to_sql
# => SQL query for you database.
Libray.joins(:book).explain
# => Database explain for the query.

4位 find_by(Rails 4 のみ)

Rails で書いたコードは次のような行で散らかったものになりやすい。

Book.where(:title => 'Three Day Road', :author => 'Joseph Boyden').first

代わりに、 find_by というショートカットメソッドが使える。

Book.find_by(:title => 'Three Day Road', :author => 'Joseph Boyden')

これは上と同じものが実行される。

注意:最先端を行く人は今すぐ find_by を使いたくなっていることだと思う。これは Rails 3 ではなく、 Rails 4 で利用できる。

3位 scoping

scope メソッドを特定の Relation として使える。Rails のドキュメントにある次の例を検討してみよう。

Comment.where(:post_id => 1).scoping do
  Comment.first # SELECT * FROM comments WHERE post_id = 1
end

これはまったくもって使いやすい。

2位 pluck

特定のレコードのカラムで配列にしたいことがないだろうか?私はこういうにを本当にたくさん見てきた。

published_book_titles = Book.published.select(:title).map(&:title)

さらに悪い場合だとこうだ。

published_book_titles = Book.published.map(&:title)

代わりに pluck を使おう。

published_book_titles = Book.published.pluck(:title)

(訳注: Rails 3 では、pluck の引数に指定できるシンボルは 1 つでしたが、 Rails 4 ではシンボルの配列を指定することで、属性を複数指定することができます。select で複数の属性を指定した場合と違い、2次元配列を返します。3 系でも比較的最近のバージョンで使えるはずです。)

1位 merge

僕はこの宝石なしには生きられない。しかし奇妙なことに、これはソース中にドキュメントされていないし、今まで見たガイドでも言及がない。これを使うと、結合( JOIN )ができて、結合されたモデルに対して名前付きスコープでフィルタできる。(訳注: 私見ですが、4.0.0 では merge が意図と違う動作をしないかよく確認した方がよいと思います。*1 いくつか修正が入っている4.0.1 以降でも試してみてください。)

class Account < ActiveRecord::Base
  # ...

  # Returns all the accounts that have unread messages.
  def self.with_unread_messages
    joins(:messages).merge( Message.unread )
  end
end