2011-05-27

RailsとjQueryでformの必須項目を自動強調してみた

Railsネタいっぱいたまってるんだけど全然吐き出しが追いつかない…。

基本的なアイディア

  • Model.validators を利用する
  • これを HTML に dump
  • jQuery でこれを拾って form の DOM をいじって強調する

ActiveModel には validators というメソッドがあり、これを利用するとどんな validator が定義されているかが分かる。この中でとりあえず ActiveModel::Validations::PresenceValidator がいわゆる not null 制約なので、こいつが定義されていたら

入力フォーム上では必須項目

扱いになる。これをうまいことユーザーに feedback してあげればよい。

※ 実際に動かして確認して書いているけどデモはないので各自手を動かして作ってください。

確認した環境

  • Ruby 1.8.7
  • Rails 3.0.7
  • jQuery 1.4.4

Controller

Controller はとりあえずこんな感じだとする。

def (new|edit)
  @model = Model.new
end

要は新規作成でも編集でも Model の instance を Controller のインスタンス変数に持つ場合が多いよね、ってだけ。もちろんこのまま書いても動きません。

View

template にこんなものを用意。Controller で作ったインスタンス変数の class に validators が定義されているので、そいつを呼び出して、JavaScript で扱いやすい形に整形して吐く。

<div id="model-essentials" data-fields='<%=
  @model.class.validators.select { |e|
    e.is_a? ActiveModel::Validations::PresenceValidator
  }.map { |e| e.attributes }.flatten.to_json %>'>
</div>

id は JavaScript 側から取得しやすいように付けただけで、適宜決めればよい。

JavaScript

var fields = $('#model-essentials').data('fields');
$(form item selector).each( function( i, e ) {
  var self = $(e);
  if ( $.inArray( self.attr('id'), fields ) >= 0 ) {
    self.append($('<span>').text(' ※').css('color', 'red'));
  }
});

form item selector は form の各入力項目をなめるための selector になる。また上のコードでは各入力項目に model の field と同じ id が振ってあるといういちばん簡単な状態を想定している1

ここでは form の各入力 field のラベルに相当する部分に赤い ※ を付け加えることを意図している。恐らくラベルと input タグは分離していると思うので乱暴に append しているが、構造に合わせて調整してほしい。

気づいたこと

schema や Model, Spec だけを眺めているより実際の form の形になってみた方が

「これ必須になってないけど変じゃね?」と気づきやすい

ことが分かった。仕様の確認にも使いやすいかも。

あと jQuery.data() で JSON 形式のデータを取得したら String じゃなくてちゃんと Array で返ってきた。賢い。

  1. HTML の構造がちゃんとなめやすいものになっていないと面倒くさいので、ちゃんと考えて構造を作りたいですね。まる。 

About

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