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

Rails' Wiki - AdjusterTutorial-0005 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

{{toc}}

'''今回分実装済みのサンプル:{{attach_anchor(adjuster.zip}}'''

!実装 -3-
!!作成手順
今回実装する内容、手順を、以下に示します。

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


!!1.SQLのミスを修正
*注意!!これまたミスっています。[[日程調整アプリを作ろう-7-|AdjusterTutorial-0007]]を参照下さい。
!!!該当箇所を確認
実装前にまずは、ミスを修正します。どういうミスかは新しいイベントを作成、候補日を追加して、日程調整の画面を見てみるとわかります。

{{attach_view(05-0001.gif)}}

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

事前確認したときに、一つのイベントでしか確認しなかったので気づいていませんでした。{{fn('テストもチュートリアルでやっておけば良かったと思いました。')}}
!!!原因確認
なにがいけなかったのでしょうか?

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

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

{{attach_view(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を以下のように修正します。

{{attach_view(05-0003.gif)}}

今度はuser_schedulesに、日程調整をするイベントに従属するscheduleのidを配列で渡して取得しています。
!!!修正されたか確認
画面で確認してみましょう。オッケーですね。

{{attach_view(05-0004.gif)}}

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

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

{{attach_view(05-01.gif)}}

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

{{attach_view(05-02.gif)}}

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

{{attach_view(05-03.gif)}}

!!4.各コントローラーのリストを全てリンクで繋ぐ
ばらばらだった各画面を全て繋ぎましょう。

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

{{attach_view(05-04.gif)}}

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

{{attach_view(05-05.gif)}}

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

{{attach_view(05-06.gif)}}

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

{{attach_view(05-07.gif)}}

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

{{attach_view(05-08.gif)}}

!!5.日程調整画面にInPlaceEditorを実装する
!!!ビューにin_place_editor_fieldを追加する
app/views/user_schedule/list.rhtmlの表示だけだった部分を、編集出来るようにin_place_editor_fieldに変更します。

{{attach_view(05-09.gif)}}

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

{{attach_view(05-10.gif)}}

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

{{attach_view(05-11.gif)}}

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

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

{{attach_view(05-12.gif)}}

!!!javascriptファイルを読み込む
app/views/layouts/にある、userやevent.rhmlをコピーして、app/views/layouts/user_schedule.rhtmlを作成。

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

{{attach_view(05-13.gif)}}

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

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

{{attach_view(05-14.gif)}}

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

{{attach_view(05-15.gif)}}

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

{{attach_view(05-16.gif)}}

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

{{attach_view(05-17.gif)}}

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

{{attach_view(05-18.gif)}}

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

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

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

{{attach_view(05-19.gif)}}

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

{{attach_view(05-20.gif)}}

!!!in_place_edit_forを修正する

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

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

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

{{attach_view(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行目がポイントです。

{{attach_view(05-21.gif)}}

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

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

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

{{attach_view(05-22.gif)}}

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

{{attach_view(05-23.gif)}}

確認してみましょう。

{{attach_view(05-24.gif)}}

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

{{attach_view(05-25.gif)}}

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

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

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

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

||[[目次|AdjusterTutorial]]||[[前ページへ|AdjusterTutorial-0004]]||[[次ページへ|AdjusterTutorial-0006]]||