RailsAdmin + Dragonfly + html5_validatorsでアップロード済みのファイルを認識しない

症状

RailsAdmin も html5_validators も高度すぎて全然ついていけませんが、こいつらがとても気が利いていてすごいということは分かってきました。

が、今日はちょっと困ったことの報告。それは

  • Rails 3.2.6 + RailsAdmin 0.0.5 + Dragonfly 0.9.12 + html5_validators 1.1.0 の組み合わせ
  • 画像が必須の Model を定義
  • データを編集するときにアップロード済みのファイルの存在を html5_validators が認識できずに怒られる

というものです。

怒られる部分の DOM の状態は以下のような感じ。

Model モデルの image という attribute に dragonfly の attachment を定義しています。

<div id="model_image_field"
     class="control-group dragonfly_type image_field ">
<label for="model_image" class="control-label">画像ファイル</label>
<div class="controls">
  <div class="toggle">
   <a target="blank" class="thumbnail"
      href="/media/BAhbBlsHOgZmIiAyMDEyLzA3LzMwLzEwXzQ5... ">
     <img src="/media/BAhbB1sHOgZmIiAyMDEyLzA3LzMwLzEwXzQ5... "
          alt="Bahbb1shogzmiiaymdeylza3lzmwlzewxzq5... ">
   </a>
   <input type="file"
          required="required"
          name="model[image]" id="model_image"
          data-fileupload="true">
  </div>
  <input type="hidden"
         name="model[retained_image]" id="model_retained_image">
  <p class="help-block">必須. </p>
</div>
</div>

ここで <input id="model_image" type="file" required="required"> に対して validationMessage が「ファイルを選択してください。」になっている状態です。

validity を見ると valueMissing が true です。

しかしこれって HTML を load して DOM パネル開いた段階でもう validation 終了してるんですね。すげー。

回避方法

とりあえず画像必須の Model で

 self.auto_html5_validation = false

で html5_validators を外しています。

JavaScriptでRubyのinspectのようなもの

ssoper/jquery-inspect - GitHub

jQuery plugin だけど。

jQuery plugin になってるのはたぶん window を開くとき用で、その機能なければ別に plugin でなくてもいいんじゃないかという気もするけど、まぁ便利なので。使い方は

$.inspect( obj [, output] )

だけ。output はデフォルトが alert で、console にも出せるし新しい window にも出せる。

でもこれだけだとちょっと jasmine:ci でのテストに不便なので jasmine.log() にも対応してもらった。jasmine な環境では

$.inspect( obj, 'jasmine' )

とすると便利。というかこれ console がない環境でこそ便利なんじゃないかなぁと思う。

cf.

What's the javascript equivalent of ruby's "inspect"? - Stack Overflow

Unicode数値文字参照

数値文字参照の数値の正体

絵文字の一覧を見てたんですよね。で、そのときに絵文字の記号の横にUnicodeってのが書いてあるので、これ使えば基本的に対応機種は全部絵文字になるのかーこりゃ楽ちんだと思ったわけです1。でもハタと思いました。数値文字参照の数値ってどこから出てくるの?と。

09:34:40 >wtnabe< Unicode 数値文字参照の数字ってどこから出てきてるんだ
                  ろう
09:46:48 <gunyoki> @wtnabe っ http://unicode.org/charts/
09:48:50 >wtnabe< @gunyoki あーそうか、特定のUTFではなくUnicode、えーと
                  UCS? で表現されているわけですね。
09:50:13 >wtnabe< どうやって求めればいいんだろう。UCS
09:55:48 <gunyoki> @wtnabe さっきのチャートの文字の下に書いてある数値。
                   16進数なので、10進数に基数変換。
09:57:33 >wtnabe< @gunyoki すでにデータとして(Unicodeじゃないものが)あ
                  るんで、それを自動で変換したいってことなんです。この
                  辺の話なのかなと思っているところです。
                  http://blog.livedoor.jp/dankogai/archives/51048882.html
10:07:47 <gunyoki> @wtnabe もし日本語でJIS X 0212やJIS X 0213使ってない
                   なら、UnicodeのBMPに載るでしょうから、UTF-16にする手
                   段があれば、何でもいいんじゃないですかね。
10:11:59 >wtnabe< @gunyoki 分かったような分からない感じになっておりま
                  す…。精進します。
10:28:47 <gunyoki> @wtnabe たとえばシェルスクリプトだと、こんな感じ。
                   echo -n 'あいうえお' | nkf -w16L0 | od -tu2 -w2 |
                   awk '/[0-9]* [0-9]*/ { print "&#" $2 ";" }'
10:36:11 >wtnabe< @gunyoki ははー。なんとか pack/unpack でできるところ
                  まできました。ありがとうございます。

なるほど、おおもとのコード体系なわけね。Unicode ってだけ言われると周辺のいろんなこと想像しちゃってダメです。で、バイナリのデータは手に入ってるのでこれの変換をゴニョゴニョと試みます。基本的にはいつも一緒の irb に活躍してもらいます。

10:38:26 >wtnabe< Ruby の Fixnum.to_s だけで基数変換できるって初めて知っ
                  た。なにこれエロい。
10:59:46 >wtnabe< irb で Unicode 数値文字参照(hex表記)を得る '変態'.
                  toutf8.unpack( 'U*' ).map{ |e| "&#x#{e.to_s(16)};" }
                  でおk
10:59:58 >wtnabe< たぶん
11:01:47 <liar_l> @wtnabe 以前、似たようなことをしたかった時は、"あ".
                  encode('UTF-8').codepoints とかして逃げましたが。
11:03:03 >wtnabe< @liar_l 1.9使いの方ですか
11:10:47 <liar_l> @wtnabe 普段は1.8で生きてますが。これに関しては、1.9
                  のが楽だったので……。

最初はちょっと悩んだけど、分かってしまえばチョー楽じゃね?と思ったが 1.9 はさらに上手だった。なにその .codepoints って。

Ruby で基数変換

ついでに知った基数変換はこれ実にエロい。

i.to_s( n )

で n 進数に変換できる。ri をまんま貼付けると以下のようになる。

$ ri Fixnum#to_s
------------------------------------------------------------ Fixnum#to_s
     fix.to_s( base=10 ) -> aString
------------------------------------------------------------------------
     Returns a string containing the representation of _fix_ radix
     _base_ (between 2 and 36).

        12345.to_s       #=> "12345"
        12345.to_s(2)    #=> "11000000111001"
        12345.to_s(8)    #=> "30071"
        12345.to_s(10)   #=> "12345"
        12345.to_s(16)   #=> "3039"
        12345.to_s(36)   #=> "9ix"

あ、60進数にはできんのか。ちょっと残念。でもよくよく考えるとあんまり使う機会ないかも^^;

  1. 古い情報ではバイナリ埋め込まなきゃいけないとか SJIS 依存になってるだとかいろいろ制約があるけど、数値文字参照なら安心して普通のテキストとして操作できる。 

Yapra の Feed::Custom で attribute を扱えるようにする

※ 取り込まれたのでもうこのパッチは不要です。

えー。github にアカウントは作るところまではいったのですが面倒になったのでとりあえずここに貼ります。

使い方はこんな感じ。

- module: Feed::Custom
  config:
    url: URL
    extract_xpath:
      capture: '//div[@class="FOO"]//ul'
      split: '/li'
      link:  # <- ココ
        first_node: '//a[@class="BAR"][1]'
        attr: :href
      # 従来の書き方
      title: '//a[@class="BAR"]/text()'

extract_xpath 内に書けるものは

capture
url の中で処理を開始したい node を特定する xpath
split
capture した elemens を each で回す際に分割で利用する xpath
これ以外
feed item 内に生成したい「要素」の名前を key に、「内容」となる HTML 文字列を取得したい node を特定する xpath を value にとる Hash

です。前回の話の中でチラッと言っていたのは、value は item の「内容」になるはずなのに「HTML 文字列」が取れてもあんまり嬉しくないなぁという話でした。HTML の「内容」は xpath で一発で取れるけど「属性値」も取りたいということです。

で、はたと思いついて、value をさらに first_node と attr を key に持つ Hash にしてみました。

コードはこんな感じ。ベッタベタです。いじったのは Feed::Custom ではなく MechanizeBase の方になります。

 @@ -11,7 +11,14 @@ class Yapra::Plugin::MechanizeBase < Yapra::Plugin::Base
   def extract_attribute_from element, item
     if plugin_config['extract_xpath']
       plugin_config['extract_xpath'].each do |k, v|
-        value = element.search(v).to_html.toutf8
+        value = nil
+        case v.class.to_s
+        when "String"
+          value = element.search(v).to_html.toutf8
+        when "Hash"
+          ele = element.at( v['first_node'] )
+          value = ( ele.nil? ) ? nil : ele.get_attribute( v['attr'] )
+        end
         set_attribute_to item, k, value
       end
     end

Hpricot には search() と at() があって、search() で返ってくるのは Hpricot::Elements, at() で返ってくるのは Hpricot::Elem1 でして、at() が呼べれば属性値は get_attribute() ですぐ取れます。(引数は、サンプルの YAML では symbol で書いてますが文字列でもいいです。)

最初このためにメソッドと同じ「at」を key として使おうと思ったのですが、attr と区別しにくいので first_node にしてみました。こういう要求は際限がなさそうだけど、この程度で収まるなら at() の挙動もはっきり分かるし、悪くないかな?2

あ、toutf8 を呼んでないな。んー。あれでもこれページを取得したときに toutf8 した方がいいような? 内容が短くなってからの方が判別難しくなっちゃいませんか?

cf.

p.s.

先日ぼやいていた YAML は grep まで含めて動きました。いやー便利便利。

  1. 複数見つかった場合は最初の一つ。要は search()[0] と同じと思って間違いない? 

  2. Hpricot はいろんな機能が楽に呼べるのでどういう風に YAML の形に落とし込めるように制限するかがなかなか難しいですね。 

Emacs 22.1 ports にキター

2007年7月26日 Emacs 22.1導入,Qt 4.3へ移行,Zend Framework 1.1へ更新,日本語PostgreSQLマニュアル追加,Firebug追加,Firefox 2.0.05へ更新,Linux Flashプラグイン9.0r48へ更新他|gihyo.jp

手元の環境でいつまで経っても Emacs が新しくならねぇなぁと思ったらこれは editors/emacs-devel を入れてたからか。

抜いて editors/emacs を入れ直せば 22.1 になるかな。

きたきた。抜いて入れ直せば別に /etc/make.conf とかいじる必要なし。

クロスメディアエキスパートってどうなんだ?

http://www.jagat.or.jp/cme/

今日知ったんだけど。

ものすごく範囲が広いような気がするけど、具体的にはたっかい講習とか受けないと中身分からないんだろうか。つーかこれを JAGAT がやるのもどうなのだろうと思ったり。

pukiwiki.org が引けない

自宅からは引けるんだけどな。

あー dns2.pukiwiki.org に聞きに行っちゃうとダメっぽい。

$ dig @dns2.pukiwiki.org pukiwiki.org

; <<>> DiG 9.3.1 <<>> @dns2.pukiwiki.org pukiwiki.org
; (1 server found)
;; global options:  printcmd
;; connection timed out; no servers could be reached

traceroute するとその前で止まってるように見えるけど工事か何か?

dns2.pukiwiki.org has address 61.194.40.84
 9  g2-0-n-otemachi-core3.sphere.ad.jp (203.138.68.202)  50.919 ms  47.665 ms  47.557 ms
10  210.165.241.2 (210.165.241.2)  71.892 ms  68.190 ms  68.826 ms
11  nas931.sapporo.nttpc.ne.jp (210.165.249.86)  72.344 ms  71.625 ms  70.755 ms
12  61.194.40.81 (61.194.40.81)  80.247 ms  76.258 ms  72.517 ms
13  61.194.40.81 (61.194.40.81)  3068.324 ms !H  3065.929 ms !H  3070.033 ms !H

[8/1 追記] sourceforge.jp に DNS 関連のトラブルのアナウンスが出ましたが、IP アドレスでアクセスしても使いものにならないことを把握しておられなかったので、コメント投げておきました。いずれ解決するでしょう。

[8/17 追記] 相当に放置していたようで、まだまだ復旧しないと。しかし sourceforge のアナウンスはドメインの管理を担当していない heno 氏ばかりですな。ゆう氏はドメインの管理も、今回の顛末のアナウンスも書けないくらいに忙しい? これ、無策のまま時間が経つのを待つのだとしたら、ものすごく度胸があるってことだけは間違いないなー。

そーなんですよ < 携帯サイト

PC View : Telephone : 携帯サイトの構築の苦悩(第1回)

携帯サイトはメンドイのです。でもうまく落としどころを見つけることは可能です。あとはどれだけ端末情報、キャリア情報に応じて処理を変える仕掛けをカプセル化できるかってとこなんですよね。

残念ながらそこまで本格的なノウハウはそこら辺には転がってませんが。

低血圧Support Group

おぉ。なかなか分かりやすくてよいサイトじゃ。

自分は数字的にはそれほどひどい低血圧ではないけれど、当たり前の話だけど症状の出方と数字は一致しないと。それは個人差ありますよってことですな。まぁそれほど目立つ症状があるわけではない(単に朝がちょっとつらいだけ)ではあるけれども、参考になる情報は活かしていこう。

国立大法人化、非常勤講師にしわ寄せ 33大学で賃下げ

from asahi.com

非常勤講師が居なきゃ成り立たないのにその非常勤講師の賃金を削るってどういうことやねんと。普通の会社でバイトがいないと成り立たないことが分かっていたら、バイト代下げてバイト来なくなる方が心配ですよ。

いい先生をどんどん集めるようにしないと、大学は生き残れませんぜ。

Emacs の設定追加

; TAB コードはインデントに使わない

(setq-default indent-tabs-mode nil)
; css-mode のインデントを C スタイルに
(setq cssm-indent-function #'cssm-c-style-indenter)

便利になった。

About

例によって個人のなんちゃらです