トップ «前の日記(2005-03-23) 最新 次の日記(2005-03-25)» 編集

3 日坊主日記


2005-03-24 [長年日記]

_ [Rails] Ajax してみました(2)

前回のを rails-0.11.0 の Ajax 機能を使って書き直してみました。

  • customer/edit.rhtml:
 <%= javascript_include_tag "prototype" %>
 <script>
 function set_zip() {
   var form = document.forms[0]
   <%= remote_function(:url => {:action => "set_zip"}, :complete => "set_zipCompleted(request)",
                       :with => "'id='+form.elements['customer[zip]'].value") %>
 }
 function set_zipCompleted(request) {
   var form = document.forms[0]
   var root, pref, addr, opts, opt, i
   root = request.responseXML.documentElement
   pref = root.selectSingleNode("//pref").text
   addr = root.selectSingleNode("//addr").text
   opts = form.elements['customer[pref]'].options
   for (i = 0; i < opts.length; i++) {
     opt = opts[i]
     if (opt.text == pref) {
       opt.selected = true
       break
     }
   }
   form.elements['customer[addr]'].value = addr
 }
 </script>
  • callback (onComplete) の引数 request は Ajax.Request じゃなくて transport.
  • :id => form.elements['customer[zip]'].value てどう書くのが正しいのん? どっちが裏やら表やら...

展開後はこうなります (parameters の前で折り返してます):

 <script language="JavaScript" src="/javascripts/prototype.js" type="text/javascript"></script>
 <script>
 function set_zip() {
   var form = document.forms[0]
   new Ajax.Request('/customer/set_zip', {onComplete:function(request){set_zipCompleted(request)},
     parameters:'id='+form.elements['customer[zip]'].value, asynchronous:true})
 }
 ...

_ rake kcode

rake に -Kkcode option きぼんぬ。

_ [Rails] date_select では auto_index が効かない(3)

DHH が Ticket #847 をあててくれないので (確かにこのパッチはてけとーすぎるきらいはある)、あてなくてよいように module にしてみる。

date_select を変更するのではなく、新たに date_select_with_index を定義することにしよう。

とりあえず今回は error_wrapping を考慮しない。

see: active_record_helper.rb: error_wrapping field_error_proc

action_view/helpers/date_helper.rb (date_select to_date_select_tag) をこぴぺして修正する。

 module ActionView
   module Helpers
     module DateHelper
       def date_select_with_index(object, method, options = {}, html_options = {})
         InstanceTag.new(object, method, self).to_date_select_tag_with_index(options, html_options)
       end
     end

     class InstanceTag #:nodoc:
       def to_date_select_tag_with_index(options = {}, html_options = {})
         defaults = { :discard_type => true }
         options  = defaults.merge(options)
         html_options = html_options.stringify_keys
         index =
           if html_options.has_key? "index"
             html_options.delete("index")
           elsif @auto_index
             @auto_index
           else
             nil
           end
         options_with_prefix = Proc.new { |position|
           options.merge(:prefix =>
             if index
               "#{@object_name}[#{index}][#{@method_name}(#{position}i)]"
             else
               "#{@object_name}[#{@method_name}(#{position}i)]"
             end
           )
         }
         date     = options[:include_blank] ? (value || 0) : (value || Date.today)

         date_select = ""
         options[:order]   = [:month, :year, :day] if options[:month_before_year] # For backwards compatibility
         options[:order] ||= [:year, :month, :day]

         position = {:year => 1, :month => 2, :day => 3}

         discard = {}
         discard[:year]  = true if options[:discard_year]
         discard[:month] = true if options[:discard_month]
         discard[:day]   = true if options[:discard_day] or options[:discard_month]

         options[:order].each do |param|
           date_select << self.send("select_#{param}", date, options_with_prefix.call(position[param])) unless discard[param]
         end

         return date_select
       end
     end
   end
 end

これを app/helper/application_helper.rb の頭辺りに仕込んでおけば、

 <% this_year = Date.today.year -%>
 <% @customer.children.each {|child| -%>
 <%   @child = child -%>
   <tr>
     <td><%= date_select_with_index "child[]", "birth",
 :use_month_numbers => true, :start_year => this_year-19, :end_year => this_year, :include_blank => true %></td>
   </tr>
 <% } -%>
 <% @child = Child.new -%>
 <% (3 - @customer.children.size).times {|index| -%>
 <%   index_id = "new_#{index}" -%>
   <tr>
     <td><%= date_select_with_index "child[]", "birth",
{:use_month_numbers => true, :start_year => this_year-19, :end_year => this_year, :include_blank => true}, "index" => index_id %></td>
   </tr>
 <% } -%>

といった具合に使える。

本日のツッコミ(全1件) [ツッコミを入れる]
# AYU (2006-10-12 20:04)

私も同様の問題(index)で悩まされておりましたので、やはりそうか! と合点いたしました。また、module の方も重宝させていただいております。ありがとうございました。

[]