モデリング
Created by Myriam Leggieri, @iammyr for Rails Girls Galway The basic guides that have been merged and adapted are the Ruby on Rails Tutorial, the basic RailsGirls app and the tutorials for creating thumbnails, authenticating users, adding design, deploying to OpenShift and adding comments.
アプリに何をさせたいですか?
まず、はじめに
- ユーザー(users) を認証する
- 認証されたユーザーが観光地 (place) の説明文を作成できるようにする
- 認証されたユーザーが観光地にコメント (comment) できるようにする
- 認証されたユーザーが観光地が自閉症に優しいかどうかを評価 (rate) できるようにする
これらの要件は、user、place、comment、ratingという4つの異なるリソースを識別するのに役立 ちます。
次のチュートリアルでは、評価(rating)できるようにします。
旅行者/ユーザーの認証
最初のリソースUserを作成し、認証を必須にしましょう。
Step 0: devise gem を追加
Gemfile を開いて、下記を追加してください。
gem 'devise'下記を実行して、gemをインストールします。
bundle installRailsサーバーの再起動も忘れずに行ってください
Step 1: deviseのセットアップ
ターミナル上で次のコマンドを実行してください。
rails g devise:installStep 2: deviseの設定
environmentsファイルにデフォルトのURLオプションを定義しましょう。 config/environments/development.rbを開いて、
config.action_mailer.default_url_options = { :host => 'localhost:3000' }endの前に上記の行を追加しましょう。
app/views/layouts/application.html.erbを開いて、
<%= yield %>の真上に
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>上記のコードを追記しましょう。
Step 3: Userモデルのセットアップ
ジェネレータを使用してUserモデルを作成しましょう。
rails g devise user
rake db:migrate作成されたUserモデルについて説明してください。フィールドとは何でしょうか?モデルはActiveRecord::Base というスーパークラスからDBと対話する能力を継承しています。(参照: MVC)
Step 4: 最初のuserの作成
これで準備が整ったので、最初のユーザーを作成できます。 deviseはアカウントの作成、ログイン、ログアウトなどに必要なすべてのコードとルートを生成します。
Railsサーバーが起動中であることを確認して、 http://localhost:3000/users/sign_upにアクセスしてユーザーアカウントを作成してください。
Step 5: サインインとログインのリンクを追加
あとは、ナビゲーションバーの右上に適切なリンクや、ユーザーがログインしていることに関するお知らせを追加するだけです。
app/views/layouts/application.html.erbを編集し、bodyの冒頭に次のコードを追加してください。
<p class="navbar-text pull-right">
<% if user_signed_in? %>
Logged in as <strong><%= current_user.email %></strong>.
<%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %>
<% else %>
<%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Login", new_user_session_path, :class => 'navbar-link' %>
<% end %></p>次に、ユーザーがログインしていない場合に強制的にログインページにリダイレクトするようにします。app/controllers/application_controller.rbを開き、以下のコードを
before_action :authenticate_user!protect_from_forgery with: :exceptionの後に追加してください。
ブラウザを開いて、ログインとログアウトを試してみましょう。
user_signed_in?とcurrent_user ヘルパーについて説明してください。これらはなぜ便利なのでしょうか?
変更をGitHubにadd,commit,pushしましょう! すべての変更がGitHubに反映されているのを確認しましょう:)
place
Railsのscaffold機能を使用して、2つめのリソース”place”の一覧表示、作成、削除、変更、表示するために必要なものすべてを作成できます。
rails generate scaffold place name:string address:string latitude:decimal longitude:decimal description:text picture:string user_id:integerusersと1対多の関連をサポートする user:references カラムが作成されることに注目してください。
scaffoldはプロジェクトディレクトリに新しいファイルを作成します。しかし、私たちは構造を定義(モデル化)しており、今後作成されるこのリソースのインスタンスがその構造に従い、どこかに保存される必要があります。それが、データベースです。
私たちはすでにデータベースを使用しています。(Gemfileにgem 'sqlite'が記述されています)
次のコマンドを実行して、”place”構造体をテーブルとしてデータベースに追加しましょう。
bin/rake db:migrateruby bin/rake db:migrateここでサーバーを再起動させましょう。http://localhost:3000/placesにアクセスして、”place”を扱うためのすべての機能があることを確認しましょう。Ruby on Railsのgenerate scaffoldが自動生成してくれたおかげです。
“place”の新しいインスタンスごとに、一意の識別子 “primary key”が自動的に割り当てられるため、開発者が特に指定する必要はありません。
Railsのscaffoldとは何でしょうか? migrationとは何で、なぜ必要なのでしょうか?
“place”リソースを操作するために作成されたページとその命名規則に注目してください。サーバーのログを確認して、以下のインタラクションがどのように処理されているのかを説明してください。(MVCパターンのコンテキストで)
- ブラウザは/places URL へのリクエストを行う
- Railsは/placesをplacesコントローラのindexアクションにルーティングする
- indexアクションはplaceモデルにすべてのplaceを取得するように依頼します(Place.all)
- Placeモデルはデータベースからすべてのplaceを取得します。
- Placeモデルはplaceの一覧をコントローラに返します。
- コントローラはユーザーを@users変数に保存し、indexビューに渡します。
- ビューはERBを使用してHTMLとしてレンダリングします。
- コントローラはHTMLをブラウザに返します。
作成されたコントローラがRESTfulであることに注目してください。
コントローラは ApplicationController スーパークラスから機能(モデルオブジェクトを操作したり、HTTPリクエストをフィルタリングしたり、ビューをHTMLとしてレンダリングするなどの多くの機能)を継承していることに注目してください。(参考: MVC)
app/views/places/show.html.erbを開いて次の行を削除してください:
<p id="notice"><%= notice %></p>認証されたユーザーへの通知は既にapp/views/layouts/application.html.erbファイルに追加しているので、この行は不要です。
GitHubリポジトリにadd、commit、pushを行いましょう!
リソースの関連付け
placesはusersとまだ正しく関連付けられていないことに注意してください。例えば、新しいplaceを作成する場合、Userフィールドも入力する必要があります。そして、Userのプロフィールを表示する際、userが作成した場所の一覧は表示されず、その逆も同様です。また、userアカウントを削除しても、userが作成したplacesは自動的に削除されません。
UserとPlacesの間の1対多の関連を作成しましょう。
Step 1. 1対多の関連を追加
UserとPlaceリソースの関連を適切に定義する必要があります。 userモデルに1つのuserとしてたくさんのplaceを作成できることを定義する必要があります。 app/models/user.rbを開いて、次のコードの後に
class User < ActiveRecord::Base下記のコードを追加してください。
has_many :placesplaceが、どのuserに属しているかを定義する必要があります。app/models/place.rb を開いて、次のコードの後に
class Place < ActiveRecord::Base以下のコードを追加してください
belongs_to :userStep 2: ビューをレンダリングする
app/views/places/_form.htmlを開いて、次のコードの後に
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>以下のコードを追加してください
<%= f.hidden_field :user_id, :value => current_user.id %>次に、以下のコードを削除してください
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>Step 3: 編集/削除の権限を設定する
placeの作成者だけがそのplaceを編集/削除できるようにします。
app/views/places/index.html.erbを開いて、次のコードを
<td><%= link_to 'Edit', edit_place_path(place) %></td>
<td><%= link_to 'Destroy', place, method: :delete, data: { confirm: 'Are you sure?' } %></td>下記のコードに書き換えてください。
<% if user_signed_in? %>
<% if current_user.id == place.user_id %>
<td><%= link_to 'Edit', edit_place_path(place) %></td>
<td><%= link_to 'Destroy', place, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
<% end %>これで完了です。アプリケーションに登録したuserを表示すると、placeを作成するためのフォームが表示され、作成済みのplaceを削除することもできます。
Placeのコメント
placeリソースの作成、placeとusersの関連付けを行ったのと同様に、commentリソースを作成し、commentとauthorを関連付けることができます。
rails generate scaffold comment body:text user_id:integer place_id:integer
bin/rake db:migrateサーバーを起動し、ブラウザで新しいサービスを確認してください。 その後、githubにadd, commit, pushを行ってください。
scaffoldがRailsのrouteファイルを更新し、Reviewリソースのルールが追加されたことを示してください。
##Resource Association
Step 1. 1対多の関連付け
app/models/place.rbを開いて、次のコードの後に
belongs_to :user以下のコードを追加してください
has_many :commentsapp/models/comment.rbを開いて、次のコードの後に
class Comment < ActiveRecord::Base以下のコードを追加してください
belongs_to :user
belongs_to :placeStep 2: ビューをレンダリングする
app/views/comments/_form.htmlを開いて、次のコードを
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>下記のコードに書き換えてください
<%= f.hidden_field :user_id, :value => current_user.id %>次に、下記のコードを
<div class="field">
<%= f.label :place_id %><br>
<%= f.number_field :place_id %>
</div>下記のコードに書き換えてください
<%= f.hidden_field :place_id%>app/views/places/show.html.erbを開いて、一番下のリンクの直前に下記のコードを追加してください
<h3>Comments</h3>
<% @comments.each do |comment| %>
<div>
<strong><%= comment.user_id %></strong>
<br />
<p><%= comment.body %></p>
<p><%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %></p>
</div>
<% end %>
<%= render 'comments/form' %>app/controllers/places_controller.rbを開いて、showアクション内の次のコードの後に add to show action after the row
@place = Place.find(params[:id])以下のコードを追加してください
@comments = @place.comments.all
@comment = @place.comments.buildStep 3: 編集/削除の権限を設定する
commentの作成者だけがそのcommentを編集/削除できるようにします。
app/views/places/show.html.erbを開いて、下記のコードを
<p><%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %></p>下記のコードに書き換えてください
<% if user_signed_in? %>
<% if current_user.id == comment.user_id %>
<p><%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: 'Are you sure?' } %></p>
<% end %>
<% end %>Resource Field Validation
現時点では、comment、place、userはその情報が正しいかどうかの検証が行われていません。レビューのcommentの長さの制限やuserのemailアドレスのフォーマットには制限があるべきです。
commentのbodyフィールドに長さの制限を追加しましょう。(validatesを使用します) app/models/comment.rbを開いて、’class’と’end’の間に下記のコードを追加しましょう。
validates :body, length: { maximum: 140 }140文字以上のコメントを入力しようとするとエラーが出るはずです。(試してみてください)
Finetune the routes
ルーティングの微調整
もし http://localhost:3000 にアクセスしても”Welcome aboard” のページが表示される場合、placesページにリダイレクトさせましょう。
config/routes.rbを開いて最初の行の後に以下のコードを追加しましょう
root :to => redirect('/places')ルートパス(http://localhost:3000/)にアクセスして、変更されたことを確認しましょう。
ルーティングについて、教えてください。ルーティングの順序や静的ファイルとの関係についても説明してください。
Rails 3 をお使いの方へ: この変更を適用するには、/public/ フォルダーからindex.htmlを削除する必要があります。