Ajaxでキーワードを手軽に新規登録する。

SoftwareBook2を使っていて、もし新たなキーワードを追加したくなったら、現状ではページにキーワードを追加するページへのリンクは無い...。webブラウザのアドレスバーに直接手で「http://localhost:3000/keywords」のようにURLを入力して、自分でキーワード管理ページを呼び出すのが今の状況だ。
だからといって、キーワード管理ページを呼び出すリンクをどこかに設定しても、単語一つを入力するだけなのにページが切り替わってしまい、ユーザー側から文句が出るのは目に見えている...。一番良いのはフォームのGUI部品にプルダウンリストとテキストフィールドが合体した部品*1があれば良いのだが、そのような部品は見つけることが出来なかった。
そこで、RailsAjaxの機能をちょっとだけ使って、プルダウンリストとテキストフィールドを部分的に更新するようにしてみた。選択と入力の二つのリンクがあり、あまり良いインターフェースではないが、Ajaxを使うはじめの一歩として。見た目は以下のような感じになる。

選択と入力をクリックすると、プルダウンリストとテキストフィールドが切り替わる。

app/views/layouts/softwares.rhtmlへの追記

javascriptライブラリの読み込みの設定。RailsAjaxを利用するためには以下のように設定しておく必要があるらしい。

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Softwares: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
  <%= javascript_include_tag :defaults %>......Ajaxを利用するための宣言
</head>
...(以下省略)...

app/views/models/softwares/_edit2.rhtmlへの修正

link_to_remote '新規'で作成されたリンクをクリックすると...

  • :url => {:action => 'new_keyword'}で指定したsoftwares_controller.rbのnew_keywordメソッドを呼び出す。
  • :update => 'keyword_name'で指定した<span id="keyword_name">のブロックを部分的に更新する。
...(途中省略)...
      <% unless @controller.class.hidden_field?(@action_name, 'keyword_id') %>
      <tr>
        <td class="<%= localized_label_class_on(@software, 'keyword_id') %>">
          <%= human_attribute_name(@software, 'keyword_id') %>
          <sub>
          <%= link_to_remote '選択', 
                   :update => 'keyword_name', ......一部更新するブロックを指定
                   :url => {:action => 'list_keyword'} %> |......そのとき呼び出すアクションを指定
          <%= link_to_remote '新規', 
                   :update => 'keyword_name', ......一部更新するブロックを指定
                   :url => {:action => 'new_keyword'} %>......そのとき呼び出すアクションを指定
          </sub>
        </td>
        <td>
        <span id="keyword_name">
          <%= render :partial=>"models/softwares/edit2_new_keyword" %>......この部分だけ更新される
        </span>
        </td>
      </tr>
      <% end %>
</table>
<!--[:]-->

app/views/models/softwares/_edit2_new_keyword.rhtmlファイルを追加

@new_keywordの条件によって、テキストフィールドとプルダウンリストを切り替えるようにしている。

<% if @new_keyword %>
  <%= text_field :keyword, :name, :size => 60 %>
<% else %>
  <%= collection_select :software, :keyword_id, Keyword.find(:all), :id, :name %>
<% end %>

app/controllers/softwares_controller.rbへの追記

テキストフィールドに入力した新しいキーワードを登録するため、create_keywordメソッドを追記した。

  def confirm_create
    create_keyword......キーワードの新規登録
    @software = Software.new(params[:software])
    render :action => 'new' unless @software.valid?
  end

...(途中省略)...
  
protected
  def create_keyword......キーワードの新規登録メソッドを定義
    if params[:keyword]......テキストフィールドを利用していたら、以下の処理
      @new_keyword = true
      @keyword = Keyword.new(params[:keyword])
      @keyword.save
      params[:software][:keyword_id] = @keyword.id
    end
  end
  
public
  
...(途中省略)...

  def confirm_update
    create_keyword......キーワードの新規登録
    #@software = Software.new(params[:software])......エラー対策で以下2行に書き換え
    @software = Software.find(params[:id])......エラー対策
    @software.attributes = params[:software]......エラー対策
    render :action => 'edit' unless @software.valid?
  end

...(途中省略)...

  def new_keyword......キーワード右横の新規をクリックすると呼び出される。
    @new_keyword = true
    render :partial => "models/softwares/edit2_new_keyword"
  end
  
  def list_keyword......キーワード右横の選択をクリックすると呼び出される。
    @new_keyword = false
    render :partial => "models/softwares/edit2_new_keyword"
  end
end
      • いつの頃からか、以下の手順でエラーが発生するようになってしまっていた。エラー対策はそれを回避するため。(編集→例えばタイトルを削除して→確認ボタン→未入力エラーを出す→タイトルを元に戻して確認ボタン→URLのidが消えてしまう→更新ボタンを押す→エラーに...。)

app/models/keyword.rbへの追記

キーワードの未入力チェックと、ダブリチェックを行うようにした。

class Keyword < ActiveRecord::Base
  has_many :softwares
  validates_presence_of :name
  validates_uniqueness_of :name
end


以上で、キーワードの追加が手軽にできるようになった。

*1:例:webブラウザのアドレスバーなど。コンボボックスと呼ばれている。