Create  Edit  Diff  FrontPage  Index  Search  Changes  History  Source  RSS  Note  wikifarm  Login

日程調整アプリを作ろう-5-

今回分実装済みのサンプル:adjuster.zip

実装 -3-

作成手順

今回実装する内容、手順を、以下に示します。

  1. SQLのミスを修正
  2. メニュー用のコントローラーMenuを作成
  3. メニューのviewを編集
  4. 各コントローラーのリストを全てリンクで繋ぐ
  5. 日程調整画面にInPlaceEditorを実装する

1.SQLのミスを修正

該当箇所を確認

実装前にまずは、ミスを修正します。どういうミスかは新しいイベントを作成、候補日を追加して、日程調整の画面を見てみるとわかります。

05-0001.gif

どうやら他のイベントの各自予定も引っ張ってきてるようです。

事前確認したときに、一つのイベントでしか確認しなかったので気づいていませんでした。*1

原因確認

なにがいけなかったのでしょうか?

ログを確認して、どんなSQLが発行されていたのか確認してみましょう。

/log/development.logを開きます。下記は該当箇所を見やすく整形したものです。

05-0002.gif

where節で、schedulesテーブルでevent_idでscheduleを絞り込んでいます。そしてusersとschedulesからuser_schedulesにそれぞれLEFT OUTER JOINしてますね。

これ、schedules側からのjoinでは既にschedulesが絞り込まれていますので問題ありません。

しかし、usersからLEFT OUTER JOINしてるときに、schedules側の絞り込みは全く関係なくusersとuser_schedulesを全てjoinしちゃってます。

だから、余計なuser_schedulesが表示されてしまったというわけです。

例えばこれが下記の様な構成だったらschedulesの絞り込みは機能します。

User 1 ----- n Schedule 1 ----- n UserSchedule

しかし、実際にはこのようになっているので最初に実装したSQLでは駄目だったという訳です。

User 1 ----- n UserSchedule n----- 1 Schedule n ----- 1 Event

修正

app/controllers/user_schedule_controller.rbを以下のように修正します。

05-0003.gif

今度はuser_schedulesに、日程調整をするイベントに従属するscheduleのidを配列で渡して取得しています。

修正されたか確認

画面で確認してみましょう。オッケーですね。

05-0004.gif

2.メニュー用のコントローラー、ビューを作成

さて、メニューです。単にユーザーとイベントにリンクするだけなので、publicディレクトリに静的なhtmlを用意してもいいのですが、今回はコントローラーとviewを作成します。

ruby script/generate controller menu indexと入力、実行します。

05-01.gif

出来あがったapp/controllers/menu_controller.rbを確認。このdef index;end;自体なくてもviewがあれば探しに行くので問題ないですが、残しておきます。

05-02.gif

3.メニューのビューを編集

app/views/menu/index.rhtmlに、以下のようにuserとeventのlistへのリンクを追加します。ついでにh1もAdjusterとか変えちゃいましょう。

05-03.gif

4.各コントローラーのリストを全てリンクで繋ぐ

ばらばらだった各画面を全て繋ぎましょう。

app/views/event/list.rhtmlに以下のように追加します。

05-04.gif

app/views/user/list.rhtmlに以下のように追加します。

05-05.gif

app/views/schedule/list.rhtmlに以下のように追加します。

05-06.gif

app/views/user_schedule/list.rhtmlに以下のように追加します。

05-07.gif

メニューの確認と、各ページ間を戻れるか確認しましょう。オッケーですね。

05-08.gif

5.日程調整画面にInPlaceEditorを実装する

ビューにin_place_editor_fieldを追加する

app/views/user_schedule/list.rhtmlの表示だけだった部分を、編集出来るようにin_place_editor_fieldに変更します。

05-09.gif

さっそく画面で確認してみます。あれ、エラーが出ました。

05-10.gif

14行目でcalled id for nil・・・・。あー、そうでした。in_place_editor_field(というかtext_fieldなどのヘルパーメソッド)に与えるオブジェクトは、ローカル変数ではなくインスタンス変数でなければならないのでした。以下のように変更します。

05-11.gif

今度はオッケーでしょうか?あれ?表示はされたけどクリック出来ない・・。

あー、prototypeなどのjavascriptを読み込んでませんでした。というか、レイアウトファイルを忘れてました。

05-12.gif

javascriptファイルを読み込む

app/views/layouts/にある、userやevent.rhmlをコピーして、app/views/layouts/user_schedule.rhtmlを作成。

以下のようにjavascript_include_tagを追加します。タイトルもAdjuster等に変更しましょう。

05-13.gif

今度こそ大丈夫でしょうか。画面で確認します。オッケーですね。

ちなみにまだ受け取るメソッドを実装してないので実際に値を送ってもまだ値は更新されません。

05-14.gif

viewでどんなソースが生成されているのか確認してみましょう。やってることはjavascriptとhtmlをはき出すマクロメソッドなんですね。

05-15.gif

コントローラーにin_place_edit_forを追加する

ビューで入力された値を受け取って再描画するメソッドをapp/controllers/user_schedule_controller.rbに追加します。以下のように記述します。

05-16.gif

画面で確認してみましょう。おお!出来ましたね。

05-17.gif

でも、InPlaceEditorには大きな問題があります。最初に入ってる"-"を消して、ブランクでオーケーを押してみて下さい。

05-18.gif

あらら、選択出来なくなってしまいました。実は初期値を"-"としていたのも、これが理由だったのです。

とりあえず全部"-"に戻しちゃいましょう。

InstantRailsのメニューから”Manage Rails Applications→Open a Rails Console”と選択、クリックします。

05-19.gif

Consoleで以下のように入力、値を全部更新します。

05-20.gif

in_place_edit_forを修正する

このままでは困ります。これをなんとかするためにはビューの所で、javascriptでごにょごにょやるか、コントローラーか、モデル側でどうにかするしかありません。

javascriptを書くのはこのチュートリアルの趣旨から外れますので、コントローラー側でどうにかしましょう。

まずはin_place_edit_forがどんな事をしているのか見てみます。

in_place_edit_for.gif

set_オブジェクト_アトリビュートというメソッドを動的に生成しています。つまり、今回の場合、set_user_schedule_attendというメソッドがあるのと同じという訳です。

というわけで、app/controllers/user_schedule_controller.rbにset_user_schedule_attendというメソッドを追加し、そのメソッドの中でブランクが来たら、初期値の"-"を返すようにしてしまいましょう。in_place_edit_forは不要になるのでコメントアウトします。

以下のように追加します。15行目がポイントです。

05-21.gif

と、ここで、15行目の事を実行する為だけにメソッドを追加するのはDRYじゃないとの突っ込みが。確かにその通りですね。

提言に従い、ここはbefore_saveを使用することにしましょう。

まずは、app/controllers/user_schedule_controller.rbを元に戻します(コメントアウトして一応残しておきました)。

05-22.gif

app/models/user_schedule.rbに以下のように追加します。

05-23.gif

確認してみましょう。

05-24.gif

オッケー。ちゃんと機能してます。

05-25.gif

次は?

次の実装作業では、プラグインを使い、ベーシック認証をかけます。

それから、画面を全部繋いでみると、スケジュールの場所が気にかかるので、場所を変えようかと思います。

また、トップページをメニュー画面に変更します。

時間があればvalidationもかけます。

目次前ページへ次ページへ

*1 テストもチュートリアルでやっておけば良かったと思いました。