読者です 読者をやめる 読者になる 読者になる

初めてのRailsアプリ(その4)

railsubject_04

初めてのRailsアプリ(その4)

少しづつ、RoRが好きになってきました。

5. 三角関係

下図のような三角関係(何の?)を実現する。

  • list(メーリングリストを想定)を作成する
  • メーリングリストにはuserとcompanyを登録できる
  • メーリングリストにはuserとcompanyの混合は許容しない

ER図

こんな感じ

f:id:naotooncajon:20130723002653p:image

変更点

list.rb

list_mappingsを通して、has_many throughな関係がある。

class List < ActiveRecord::Base
  attr_accessible :category, :name
  attr_accessible :user_ids, :company_ids

  has_many :list_mappings
  has_many :users, :through => :list_mappings
  has_many :companies, :through => :list_mappings
end

list_mapping.rb

中間テーブル

class ListMapping < ActiveRecord::Base
  belongs_to :user
  belongs_to :company
  belongs_to :list
end

user.rb

本筋ではないが、name_addressメソッドを作成

class User < ActiveRecord::Base
  attr_accessible :address, :name

  def name_address
    return "#{name}@#{address}"
  end
end

company.rb

本筋ではないが、name_addressメソッドを作成

class Company < ActiveRecord::Base
  attr_accessible :address, :name

  def name_address
    return "#{name}@#{address}"
  end
end

_form.html.erb

変更点は以下

  • categoryをselectに変更
  • ユーザ(id=user_field)および企業(id=company_field)のmultiple selectを追加

ソース

<%= form_for(@list) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :category %><br />
    <%= f.select :category, {"user" => "user", "company" => "company"} %>
  </div>
  <div class="field" id="user_field">
    <%= f.label "アドレス一覧" %><br />
    <%= f.select :user_ids, User.all.map{|t| [t.name_address, t.id]}, {}, :multiple => true %>
  </div>
  <div class="field" id="company_field">
    <%= f.label "アドレス一覧" %><br />
    <%= f.select :company_ids, Company.all.map{|t| [t.name_address, t.id]}, {}, :multiple => true %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

javascript

このままだと、ユーザと企業を混合して登録ができてしまう。(まあ別にそれでも構わんが)今回は、categoryを選択した際の処理をjavascriptに記載する。

  • 確認ダイアログを表示
  • ユーザと企業の表示/非表示を切り替え
  • 選択済みを非選択化

ソース

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
  $(function(){
    // 「id="company_field"」を非表示
    $("#company_field").css("display", "none");

    // 「id="list_category"」がクリックされた場合
    $("#list_category").change(function(){
      // 確認ダイアログを表示
      if(window.confirm('カテゴリを変更すると、これまでの入力内容が破棄されます。変更してもよろしいですか?')){
        // OKの場合
        // 「id="user_field" / "company_field"」の表示、非表示を切り替える
        $("#user_field").toggle();
        $("#company_field").toggle();

        // 「id="user_field" / "company_field"」を非選択状態にする
        $("#list_user_ids").children().removeAttr('selected');
        $("#list_company_ids").children().removeAttr('selected');

      }else{
        // NGの場合

      }
    });
  });
</script>

完成形

切り替わりますた。企業を選んでいる場合

f:id:naotooncajon:20130723002656p:image

ユーザを選んでいる場合

f:id:naotooncajon:20130723002659p:image

終わりに

いまさらですが、企業とユーザの混合を許容しても良かったかなとおもいます。まあ仕様書にそう書いちゃったし。今後やりたいこと。

  • groupでsubjectを選択する際のUI高度化
  • mailでメールを送る
  • activerecordについてのお勉強