Rails

RailsTutorial 3日目

More than 3 years have passed since last update.

Ruby on Rails tutorial http://railstutorial.jp/ より、「第2章デモアプリケーション

RailsTutorial 1日目

RailsTutorial 2日目


Micropostsリソースを作って、Usersリソースと関連付ける


Micropostsリソースを作る

マイクロポストのデータテーブルは以下。

Microposts table

id(integer)

content(string)

user_id(integer)

参考)2日目で作ったユーザーテーブル

Users table

id(integer)

name(string)

email(string)

$ rails generate scaffold Microposts content:string user_id:integer

$ bundle exec rake db:migrate

これによって、新しくデータベースが作成され、ルーティングのルールがcongif/routes.rbに加えられる。また、app/controllers/microposts_controller.rbapp/models/micropost.rbapp/views/microposts/も作成される(他にも色々作成されるけど)。


config/routes.rb

FirstApp::Application.routes.draw do

resources :microposts
resources :users



localhost:3000/micropostsにアクセスすることで、usersのときと同じようなページ、アクションを行うことを確認することができる。


Micropostのcontentに文字数制限を加える

モデルにvalidatesを加える


app/models/micropost.rb

class Micropost < ActiveRecord::Base

validates :content, length: { maximum: 140 }
end


MicriopostとUserを紐付ける

モデル


  • 1人のユーザーに複数のマイクロポストがある。

  • 1つのマイクロポストは1人のユーザーにのみ属する。

ということを書き加える。


app/models/user.rb

class User < ActiveRecord::Base

has_many :microposts
end


app/models/micropost.rb

class Micropost < ActiveRecord::Base

belongs_to :user
validates :content, length: { maximum: 140 } #さっき加えたvalidate
end

改行するだけで、;とかはいらない。

関連付けとvalidate、書く順番は関係ないのかな?どっちを先に書いておいたほうがいいんだろう。関連付けが最初に書いてあったほうが見通し良さそう。


Rails consoleで紐付けを確認する

これだけでは、ブラウザからアクセスしてMicropostとUserが紐付けられたことを確認することはできない。

rails consoleコマンドで、コマンドラインからデータの紐付けだけを確認する。

$ rails console

Loading development environment (Rails 4.0.5)
irb(main):001:0> first_user = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: 1, name: "suzuki", email: "hoge@hoge.com", created_at: "2015-03-28 09:36:25", updated_at: "2015-03-28 09:39:57">
#first_userに1番目のユーザーの情報がはいった。

irb(main):002:0> first_user.microposts
Micropost Load (2.4ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? [["user_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 1, content: "こんばんわこんばんわ!", user_id: 1, created_at: "2015-05-10 10:38:00", updated_at: "2015-05-10 10:38:00">, #<Micropost id: 3, content: "こんにちわ!", user_id: 1, created_at: "2015-05-10 10:39:45", updated_at: "2015-05-10 10:39:45">]>
#1番目のユーザーに紐付けられているmicropostsが全て表示された

2番目のユーザーはどうするんだろうと思って、

secound_user = User.secound, secound_user = User[1]とかやってみたけどダメだった。そのうち出てくるかな。

consoleの終了にはexitコマンド。Control+Cだと終了しなかったや…。


紐付けられる側(マイクロポスト側)って書く必要あるの?


  • 1人のユーザーに複数のマイクロポストがある。

が必要なのはわかるけど


  • 1人のユーザーに複数のマイクロポストがある。

はなくてもいいんじゃないのかな?と思って、


app/models/micropost.rb

class Micropost < ActiveRecord::Base

#belongs_to :user
validates :content, length: { maximum: 140 } #さっき加えたvalidate
end

にして、rails consoleで同じように確認してみたら、同じように動作した。

Railsとしては両方書かなくても動くけど、作ろうとしているマイクロポストサービスには必要な要件だから今回書いているということ。(このtweetはどのUserのものか)

いざサービス作るときに、データベースの設計とかすごい大事!


継承の階層?

オブジェクト指向わからないけど読んでみた。


モデル

UsersモデルとMicropostsモデルは、どちらもActiveRecord::Baseというクラスを継承している。


Active Recordはデータベースからデータを読み出すためのアプローチである。

http://ja.wikipedia.org/wiki/Active_Record



app/models/user.rb

class User < ActiveRecord::Base

.
.


app/models/micropost.rb

class Micropost < ActiveRecord::Base

.
.

継承することで、UsersモデルオブジェクトとMicropostsモデルオブジェクトはデータベースにアクセスすることができる。(「継承」「モデルオブジェクト」がわからない)


ActiveRecord::Baseクラスを継承したことによって、作成したモデルオブジェクトはデータベースにアクセスできるようになり、データベースのカラムをあたかもRubyの属性のように扱えるようになります。


ここが大事な気がした。


コントローラ

UsersコントローラとMicropostsコントローラはいずれもApplicationControllerを継承している。


app/controllers/users_controller.rb

class UsersController < ApplicationController

.
.


app/controllers/microposts_controller.rb

class MicropostsController < ApplicationController

.
.


app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

.
.

application_controller.rbは、rails newしたときに作られたもの。

Applicationコントローラが継承している、ActionController::Baseは、RailsのAction Packというライブラリが提供している、コントローラ用のベースクラス。

ActionController::Baseは、いろんな機能をもっていて、RailsのコントローラはすべてActionController::Baseを継承するApplicationControllerを継承しているから、コントローラー全てでActionController::Baseの機能を使用することができる。

また、ApplicationControllerで定義されたものは、他のコントローラーでも使用することができる。

(コントローラとControllerの表記が混じっているけれど、コントローラは一般的/概念的?な意味で、Controllerはファイルとか実際に存在/動作するもの、みたいなイメージで書き分けている)


commitしてデプロイしよう

$ git add .

$ git commit -m "UsersリソースとMicropostsリソースを追加"
$ git push origin master
$ git push heroku master
$ heroku run rake db:migrate
$ heroku open

herokuでrakeするときは、bundle execいらないのかなぁ?

heroku上ではグローバルって概念がないから、bundle execでプロジェクト内のgemをみなくてもいいってことなのかな。

heroku openでブラウザで開いて確認。トップページはエラーが出るけど、/micropostsと/usersにアクセスして表示されることを確認した。