Hatena::ブログ(Diary)

mizchi log

@mizchiの雑記帳

2012-02-13

ゼロからRails入門するよ〜


Railsは「命名規約によって、DSLから機能を動的に生成するもの」でいいのかな?
某記事で声がかかった企業のうち、面談行ってるのが3社で、そのうち2社がRailsつかってるので、前々から興味あったし手を出すことにした。勉強するならよそでやれ(棒)なんて話、流行ってますね。僕はどっちでもいいけど。


これはRuby on Rails 3.1で簡単なブログっぽいシステムを作ってみるテスト。 | Ginpen.comを読みながら勉強しつつのメモなので、間違ってる箇所があったら教えてください。この記事は全部一通りやりました。

主にPython使ってたので、Rubyはあんま詳しくないです。

インストール

ひさしぶりにRubyを使うので、gem本体のアップデートから。

sudo gem update --system 
sudo gem install rails

railsが3.2.1が入った。gemが推奨するから現行Verなのかなってことで、これを使っていく。
使ってるRubyはHomebrewからいれた1.9.2-p180。rvm使ったほうがいいんだろうけど、それはまたあとで。
/usr/local/Cellar/ruby/1.9.2-p180/bin/ にパスを通してgemでインストールしたスクリプトにパスを通す。

プロジェクトを作成

$ rails new myrails
$ cd myrails
$ bundle install 

たぶん初回newしたときは大量のライブラリをinstallすることになるので、結構時間がかかる。

rails s

で起動。s はserverの略。http://localhost:3000/

bundlerとGemfile

ルートのGemfileには使用する外部ライブラリを記述する。
bundlerはプロジェクトルートで $bundle install することでGemfileに記述されたgemライブラリをプロジェクトに引っ張ってくる。

(Railsの)MVC

CotnrollerはURLのリクエストを受けてModelを操作する。
ControllerはViewにModelを渡し、ViewはModelによってHTMLやJSONを生成して返す。
デフォルトのテンプレートエンジンはerb。これはあんまりいじらないのかな?

この考え方だと、Sinatraのapp.rbはコントローラが入り口だと言えて、PHPはテンプレートエンジンが入り口だとも言える、のかな?

ActiveRecord

Railsによって生成されるモデルはActiveRecordという。データベースを抽象化する。
開発中はsqliteを、Heroku(後述)にデプロイするときはPostgreSQLを使いたい場合(使わされる)、以下のようにGemfileを書く。

group :development do
  gem 'sqlite3'
end

group :production do
  gem 'pg'
end

ActiveSupport

ActiveRecordのモデル名と品詞で動的に生成されるURL(API)をActiveSupportという。次に述べるscaffoldで自動的に生成される。
これ完全な間違い。scaffoldの機能として生成されている。
ActiveSupportはユーティリティ群らしい。

scaffold

RailsのDSLでモデルとAPIを一気に生成することができる。
たとえば、

$ rails g scaffold Post title:string body:text

これを実行した場合、Postはtitleとbodyという属性を持つ。コロンの後置の属性は型。
number(数値) string(文字列) text(複数行にわたるstring)などがあって、ぐぐればわかるだろう。

これを環境のDBとして適用させたければ

rake db:migrate

する。rakeはRubyのMakefileのようなもので、Railsのプロジェクトの自動生成によってRakefileが設定されている。


他、コントローラとビューも自動的に生成される。
モデル名postの複数形 /posts を開けばPostのアイテム一覧がみえ(キャメルケースか気にしないのは自然なURLになるように、だろう) /posts/newでは投稿用フォームが用意されていたり。
このときのAPIは /app/controller/posts_controller.rb に記述されていて、たとえば

class PostsController < ApplicationController
  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @posts }
    end
  end
...

というようにコメントの解説付きで記述されている。
このindexメソッドではPostのすべての要素 @postsを引数に、app/view/posts/index.html.erbをビューとして構成し、クライアントに返す。ということだろう。

rails consoleで対話インタプリタ

$ rails console でrailsのAPIにアクセスできる irbが立ち上がる。
なにか適当に保存してからみてみよう。

irb(main):001:0> Post.first
  Post Load (0.2ms)  SELECT "posts".* FROM "posts" LIMIT 1
=> #<Post id: 1, title: "Hello!", body: "this is my blog test", created_at: "2012-02-12 20:11:07", updated_at: "2012-02-12 20:11:07">

Post.first(一番最初の項目を呼び出し)すると、title、bodyの他にid,, created_at, updated_atがみえる。これはActiveRecordによって自動的に生成されたものだろう。

(このとき rails console --sandbox 属性をつければモデルへの変更は保存されない)

Heroku

Paas。多言語対応だがRubyのデファクト
飽きてきたのであとで書く。

モデルのスキーマを変更したい場合

rails destroy scaffold Post
rake db:drop
rails g scaffold Post ~

Herokuならこれに

herokue run rake db:drop 

が必要。これでちょっと詰まった。

リレーショナルなモデルの作成

上記のチュートリアルでやったこと。
scaffoldでcommentを作成する。

rails g scaffold Comment post:references body:text 

references属性をつけてCommentからPostを引けるよう設定。

PostがCommentを複数もっている場合(1対多)
次のように手で書き換える。

app/model/comment.rb

class Comment < ActiveRecord::Base
  belongs_to :post
end

app/model/post.rb

class Post < ActiveRecord::Base
	has_many :comments
end

ビューの細かいパラメータについては後で。

感想

結局、Railsがいくら自動で生成してくれるといっても、生成されるcontrollerとviewはお決まりの形なので、これを元に自力で書き換えていく。自分がやりたいことをどのようにDSLとRubyで実現できるか、それを調べる力が必要で、レシピブックみたいなのを一冊持っておくと便利なのだろう。

で、他人が実装したレシピを自分のやりたいことの差分を調べ、最小労力で目的を達成する、というのがRailsのコンセプト、かな。
まあ実際いろいろと歪みもあるらしいけど、レールの上に乗っかってるうちは高速に開発ができるんだろう。