RoR で実現する Ajax アプリ (写経) その 3
写経を続行。
アイテムを作る
task コントローラのタスクリスト部分の機能追加。{修正, 追加}したソースを以下に。
- app/views/task/_list.rhtml
<div class='tasklist'> <h2 id='tasklist_<%= list.id %>'><%= h list.title %></h2> <div class='list_menu'> <%= link_to_function 'ADD', "Element.toggle('add_item_#{ list.id }')", :class => 'menu_link' %> <%= link_to_remote 'DELETE', { :url => { :controller => 'ajax', :action => 'destroy_list', :id => list.id }, :success => "Element.remove($('tasklist_#{ list.id }').parentNode)", :confirm => "「#{list.title}」を削除します。\nよろしいですか?" }, :class => 'menu_link' %> <%= form_remote_tag :url => { :controller => 'ajax', :action => 'add_item', :id => list.id }, :failure => 'alert(request.responseText)', :complete => "Element.hide('add_item_#{ list.id }')", :position => :bottom, :update => { :success => "list_#{ list.id }" }, :html => { :style => 'display:none;', :id => "add_item_#{ list.id }" } %> <%= text_field_tag 'note', nil, :id => "note_#{ list.id }" %> <br /> <%= submit_tag 'ADD' %> <%= link_to_function 'cancel', "Element.hide('add_item_#{ list.id }')" %> <%= end_form_tag %> </div> <ul id='list_<%= list.id %>'> <% unless list.items.empty? -%> <%= render :partial => 'item', :collection => list.items %> <% end -%> </ul> </div>
- app/controllers/ajax_controller.rb (追加分のみ)
def destroy_list render_destroy List.find(params[:id]) end def add_item item = Item.new( :list_id => params[:id], :note => params[:note] ) render_add(item, 'item') end protected def render_destroy(ar) ar.destroy render :nothing => true end
app/views/task/_item.rhtml
<li id='item_<%= item.id %>'> <%= h item.note %> </li>
タイプミス等の細かいミスはありましたが、その 1 で作成した 001_initial_schema.rb で大ボケをぶちかましています。note というカラムを作成しておらぬ。(駄目スギ
とりあえず、まとめでキチンとする、ってコトでここは SQL で誤魔化す。(こら
mysql> alter table items add note text ; Query OK, 0 rows affected (1.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc items ; +------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | | auto_increment | | list_id | int(11) | YES | | | | | completion | tinyint(1) | YES | | 0 | | | position | int(11) | YES | | | | | created_on | time | YES | | | | | updated_on | time | YES | | | | | note | text | YES | | | | +------------+------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec) mysql> \q Bye
とほほほ ...
とりあえず、item の追加はデキた模様。
# それにしてもスタイルシートを何もしてないので見栄えが最低。
なんか全然 javascript 使わずに ajax 実装してるんで微妙なんですが、link_to_function と form_remote_tag の組み合わせで、ぼよよんとフォームが現われて、なナニが実装できる、とゆー事が分かった。直前エントリで出てきた link_to_remote も画面遷移を伴なわない、というアレな機能の実装が可能、という事ッスか。
あと、item があれば表示、というロジックも非常に簡易に実装できる事が分かる。ajax 凄いなぁ、というのもですが、とりこんじゃってる RoR 凄スギ。
render_add というメソドの使い方も RoR の機能(??)として素晴しひ。
アイテムにチェック機能を付ける
チェック入れたらその item は完了状態に、という機能の実装。view と controller に修正が入る。修正後のソースは以下。
app/views/task/_item.rhtml
<li id='item_<%= item.id %>' class='<%= item.completion ? 'completion' : 'not_completion' %>' > <%= check_box_tag('check', '1', item.completion, :id => "completion_#{ item.id }" ) %> <%= observe_field "completion_#{ item.id }", :url => { :controller => 'ajax', :action => 'completion_item', :id => item.id }, :complete => %Q[$("item_#{ item.id }").className == "not_completion" ? $("item_#{ item.id }").className = "completion" : $("item_#{ item.id }").className = "not_completion"] %> <%= h item.note %> </li>
app/controllers/ajax_controller.rb (の一部)
public def completion_item item = Item.find(params[:id]) item.toggle! :completion render :nothing => true end
_$ ふんちゃら_、という構文が出てきているな。意味分からんままやっています。とりあえず全部を実装した時点でまとめを作りたいと。(と言いつつヤラない事が多いが、rails についてはきちんと見ないと理解できんので)
アイテムに編集機能を付ける
script.aculo.us の In Place Editor という機能を使う、との事。編集したいテキストをクリックしたらテキストボックスになる、というアレ。ここでも修正は view と controller となる、との事。修正後のソースを以下に。
app/views/task/_item.rhtml
<li id='item_<%= item.id %>' class='<%= item.completion ? 'completion' : 'not_completion' %>' > <%= check_box_tag('check', '1', item.completion, :id => "completion_#{ item.id }" ) %> <%= observe_field "completion_#{ item.id }", :url => { :controller => 'ajax', :action => 'completion_item', :id => item.id }, :complete => %Q[$("item_#{ item.id }").className == "not_completion" ? $("item_#{ item.id }").className = "completion" : $("item_#{ item.id }").className = "not_completion"], :update => "", :position => :bottom %> <span class='item_edit_area' id='item_edit_area_<%= item.id %>'><%= h item.note %></span> </li> <script type="text/javascript"> new Ajax.InPlaceEditor( 'item_edit_area_<%= item.id %>', '<%= url_for :controller => 'ajax', :action => 'edit_item', :id => item.id %>', { onComplete: function(transport, element) { if(element.innerHTML.length == 0){ Element.remove(element.parentNode); } } } ) </script>
app/controllers/ajax_controller.rg (一部のみ)
def edit_item item = Item.find(params[:id]) if params[:value].strip.empty? render_destroy item else item.note = params[:value] item.save render :text => item.note end end
編集できるようになったんですが、テキストボックスを空にして修正しても見栄え上は箇条書きの_・_が残ったママとなる。未確認ですがデータ的には削除されている模様。リロードしたら消えます。微妙な不具合がん残っているに違いない。色々とイヂくる余地が残っているな。現時点ではスルーさせて頂きます。
とりあえず、D&D でアイテム移動、などという機能の実装が残っていますが、若干消化不良なんでもすこし噛み砕く暇を下さひ。