実行環境:
ruby 1.9.3
Rails 3.1.3
composed_of宣言を使うとテーブルの2つのカラムを疑似的に1つのカラムにまとめることができます。ruby 1.9.3
Rails 3.1.3
DBのテーブル上は、「苗字」カラムと「名前」カラムが別になっているが、Rails上はフルネームで扱いたい、なんて場合があります。あるいは住所情報が「都道府県」、「市区町村」、「それ以降の住所」と3つに分かれてテーブルに保存されているのを「住所」という1カラムとして扱いたい、なんて場合もあります。
集約によるデータの合成
例としてこんなテーブルがあったとします。usersテーブル | |
---|---|
カラム1 | id |
カラム2 | myoji |
カラム3 | namae |
カラム4 | myoji_yomi |
カラム5 | namae_yomi |
【目標】:「myoji」と「namae」カラムをスペースでつないだ文字列が「fullname」で参照できるようにする
集約のためのFullNameクラスを定義する
集約のためのルールを定めるクラスを作成します。とりあえずmodelの定義ファイルの中で定義します。class User < ActiveRecord::Base end class FullName attr_reader :family_name, :given_name def initialize(family_name, given_name) @family_name = family_name @given_name = given_name end def to_s [@family_name, @given_name].compact.join(" ") end end
テーブル上のカラムとの対応付けを行う
composed_of宣言を使ってfullnameという名前のプロパティ(?)を定義します。元々のテーブルのどのカラムが指定したFullNameクラスのどの変数に対応するかをマッピングします。# 省略 endclass User < ActiveRecord::Base composed_of :fullname, :class_name => "FullName", :mapping => [ [ :myoji, :family_name ], [ :namae, :given_name ] ] end class FullName
こうすることで、user.fullname という形で参照することができます。
FullNameクラスのインスタンス変数(family_name, given_name)にアクセサメソッドを定義しているので以下のような参照も可能です。 <%= @user.fullname %>
もともとのカラムにもアクセスできます。 <%= @user.fullname.first_name %> <%= @user.fullname.given_name %>
<%= @user.myoji %> <%= @user.namae %>
集約したfullnameに値を代入することはなんだかできないようです。値を変更する場合は、もともとのカラムの値を変えるようにすればいいのかな…?
集約に使うクラスを使い回す
定義したFullNameクラスを「myoji」と「namae」カラムの集約に使いましたが、「myoji_yomi」と「namae_yomi」カラムの集約にも使えます。# 省略 end参照はこんな感じで。 class User < ActiveRecord::Base composed_of :fullname, :class_name => "FullName", :mapping => [ [ :myoji, :family_name ], [ :namae, :given_name ] ] composed_of :fullkananame, :class_name => "FullName", :mapping => [ [ :myoji_yomi, :family_name ], [ :namae_yomi, :given_name ] ] end class FullName
複数のモデルでFullNameクラスを使い回すこともできそうです。そうなってくるとFullNameクラスの定義をする場所はもっといい場所があるかもしれません。(例えば#{RAILS_ROOT}/config/initializers/の中とか??) <%= @user.fullname %> <%= @user.fullname.first_name %> <%= @user.fullname.given_name %> <%= @user.fullkananame %> <%= @user.fullkananame.first_name %> <%= @user.fullkananame.given_name %>
結合した値の参照だけならメソッドでいいんじゃない? composed_of の使い方を書いてきましたが、単に fullname を参照するだけならモデルの中にメソッドを定義すればよいような…
class User < ActiveRecord::Base def fullname "%s %s"%([self.myoji, self.namae]) end end
0 件のコメント:
コメントを投稿