モデリング

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 install

Railsサーバーの再起動も忘れずに行ってください

Step 1: deviseのセットアップ

ターミナル上で次のコマンドを実行してください。

rails g devise:install

Step 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
Help from the coach

作成された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の後に追加してください。

ブラウザを開いて、ログインとログアウトを試してみましょう。

Help from the coach

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:integer

usersと1対多の関連をサポートする user:references カラムが作成されることに注目してください。

scaffoldはプロジェクトディレクトリに新しいファイルを作成します。しかし、私たちは構造を定義(モデル化)しており、今後作成されるこのリソースのインスタンスがその構造に従い、どこかに保存される必要があります。それが、データベースです。

私たちはすでにデータベースを使用しています。(Gemfileにgem 'sqlite'が記述されています) 次のコマンドを実行して、”place”構造体をテーブルとしてデータベースに追加しましょう。

bin/rake db:migrate
ruby bin/rake db:migrate

ここでサーバーを再起動させましょう。http://localhost:3000/placesにアクセスして、”place”を扱うためのすべての機能があることを確認しましょう。Ruby on Railsのgenerate scaffoldが自動生成してくれたおかげです。 “place”の新しいインスタンスごとに、一意の識別子 “primary key”が自動的に割り当てられるため、開発者が特に指定する必要はありません。

Help from the coach

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 :places

placeが、どのuserに属しているかを定義する必要があります。app/models/place.rb を開いて、次のコードの後に

class Place < ActiveRecord::Base

以下のコードを追加してください

belongs_to :user

Step 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を行ってください。

Help from the coach

scaffoldがRailsのrouteファイルを更新し、Reviewリソースのルールが追加されたことを示してください。

##Resource Association

Step 1. 1対多の関連付け

app/models/place.rbを開いて、次のコードの後に

belongs_to :user

以下のコードを追加してください

has_many :comments

app/models/comment.rbを開いて、次のコードの後に

class Comment < ActiveRecord::Base

以下のコードを追加してください

belongs_to :user
belongs_to :place

Step 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.build

Step 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/)にアクセスして、変更されたことを確認しましょう。

Help from the coach

ルーティングについて、教えてください。ルーティングの順序や静的ファイルとの関係についても説明してください。

Rails 3 をお使いの方へ: この変更を適用するには、/public/ フォルダーからindex.htmlを削除する必要があります。