テーブル関連は、ややこしい...

えー、紆余曲折で、とりあえず、片が付きそうなんでwww


えーっと、ですね。
ユーザ間のメッセージ機能を作ろうと思いまして。
いや、だって、お友達機能作ったら、今度は、お友達になりたいヤツを探して、「お友達になろうよ」ってメッセージを投げて、んで、相手に「ん、いいよ、なろうなろう」って云ってもらわないと、相互認識上の友人関係は、成立しない訳じゃん?


つうか、それも寂しい世の中だよねwww


んじゃあ、メッセージ機能を作りましょう。
で、どうせ作るのなら、ユーザ間だけでは無くって、オーサー側からのアナウンスメントも投げられるようにしましょうよ。
なんで、汎用性のある、メッセージ機能を作る。
で、メッセージのタイプも作る。


メッセージのタイプは、とりあえず、

  • オーサーからのアナウンスメント(全てのユーザへ)
  • オーサーからの注意(個人のユーザへ)
  • ユーザからユーザへ(お友達になろうよメッセージ)
  • ユーザからユーザへ(普通の個人間メッセージ)

くらいかね。


まず、メッセージの種類のモデル。

$ script/generate model MessageType name:string

メッセージの種類は、、config.ymlで書いちゃいましょうかね。
だって、そうすると、マイグレーション・ファイルの中では、ブロックで回せば、メッセージの種類が今後増えたとして、マイグレーション・ファイルを編集する必要は無いからね:-)
config/config.yml

development:
(略)
  message_type:
    announcement:           announcement
    notice:                 notice
    be_friend:              be_friend
    to_friend:              to_friend
(略)
test:
(略)
  message_type:
    announcement:           announcement
    notice:                 notice
    be_friend:              be_friend
    to_friend:              to_friend

んー、なんか、DRYじゃあ、ないよねぇ...
まあ、その辺は、あとで考えようwww


んで、マイグレーション・ファイルの編集。
db/migrate/*数字*_create_message_type.rb

class CreateMessageTypes < ActiveRecord::Migration
  def self.up
    create_table :message_types do |t|
      t.string :name, :limit => 40, :null => false 
      t.text    :description

      t.timestamps
    end
  end

  def self.down
    drop_table :message_types
  end
end

んで、初期データのマイグレーション・ファイルの作成。

$ script/generate migrate AddInitialDataToMessageType

んで、編集。

class AddInisialDataToMessageType < ActiveRecord::Migration
  def self.up
    APP_CONFIG["message_type"].values.each do |message_type_name|
      unless MessageType.find_by_name(message_type_name)
        MessageType.create( :name => message_type_name,
                            :description => "The type of this message is the one for #{message_type_name}.")
      end
    end
  end

  def self.down
    APP_CONFIG["message_type"].values.each do |message_type_name|
      message_type = MessageType.find_by_name(message_type_name)
      message_type.destroy
    end
  end
end


よし。


んじゃあ、Messageモデルを作ろう。

$ script/generate model Message message_type_id:integer sender_id:integer reciever_id:integer subject:string body:text senders_state:string recievers_state:string

こんな感じ。


ん? senders_state? Recievers_state?
はい。state。
ちょっと、ここで、aasmで使ってみようかな、と。
だって、restful_authenticationの為だけだなんて、もったいないじゃない?www
そりゃあもう、ワンガリ・モータイさんにリスペクトですよ、ここわ。
むしろ、日本人としての誇りってやつですよ。


まあ、例の運動に関しては、売日新聞が絡んでるんで、関わりませんがねっwww


で、マイグレーション・ファイルの編集。

class CreateMessages < ActiveRecord::Migration
  def self.up
    create_table :messages do |t|
      t.integer :message_type_id,                         :null => false
      t.integer :sender_id,                               :null => false
      t.integer :reciever_id,                             :null => false
      t.string  :subject,         :length => 64,          :null => false
      t.text    :body,                                    :null => false
      t.string  :senders_state,   :default => "passive",  :null => false
      t.string  :reciever_state,  :default => "passive",  :null => false

      t.timestamps
    end
  end

  def self.down
    drop_table :messages
  end
end

ふう、やっと、マイグレート、だよ;-)

$ rake db:migrate


よし。
んで、双方の関連付け。
app/models/message_type.rb

+  has_many :messages

app/models/message.rb

+  belongs_to :type,   :foreign_key => :message_type_id,
+                      :class_name => "MessageType"

なんか、メッセージのタイプを知るのに、「message.message_type」なんて、冗長だよね?www
やっぱり、ここは、「message.type」にならないと、ねぇ?
(まあ、ナニゲに、ここで結構詰まっていたりなんかもしたんですがwww)


おk。
おk?


んじゃあ、テストしようじゃまいか。


まず、フィクスチャ。
test/fixtures/messages_type.yml

# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

announcement:
  id:             1
  name:           announcement
  description:   The type of this message is the one for announcement.

notice:
  id:             2
  name:           notice
  description:    The type of this message is the one for notice.
be_friend:
  id:             3
  name:           be_friend
  description:    The type of this message is the one for be_friend.
to_friend:
  id:             4
  name:           to_friend
  description:    The type of this message is the one for to_friend.

test/fixtures/message.yml

# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

from_quentin_to_aaron:
  message_type_id:  4
  sender_id:        1
  reciever_id:      2
  subject:          題名のない音楽会その1
  body:             黛敏郎です。
  senders_state:    sent
  reciever_state:   pending

from_aaron_to_quentin:
  message_type_id:  3
  sender_id:        2
  reciever_id:      1
  subject:          題名のない音楽会その2
  body:             佐渡 裕って誰だよ。
  senders_state:    sent
  reciever_state:   opened

from_admin_to_quentin:
  message_type_id:  1
  sender_id:        4
  reciever_id:      1
  subject:          アナウンスメント
  body:             啓蒙的なヤツ。。
  senders_state:    sent
  reciever_state:   pending


んで、message_type_test。
test/unit/message_type_test.rb

require File.dirname(__FILE__) + '/../test_helper'

class MessageTypeTest < ActiveSupport::TestCase
  test "should message type has messages" do
    message_type = message_types(:announcement)
    assert_equal(message_type.messages.count, 1)
  end

  test "should message type get message's subject through messages" do
    message_type = message_types(:announcement)
    message = message_type.messages[0]
    assert_equal(message.subject, "アナウンスメント")
  end
end

おk。


んじゃあ、message_test。
test/unit/message_test

require File.dirname(__FILE__) + '/../test_helper'

class MessageTest < ActiveSupport::TestCase
  test "should message has type" do
    message = messages(:from_quentin_to_aaron)
    assert(message.type)
  end

  test "should message get message types attribute through type" do
    message = messages(:from_aaron_to_quentin)
    assert(message.type.id)
    assert_equal(message.type.name, "be_friend")
    assert_equal(message.type.description, "The type of this message is the one for be_friend.")
  end
end

ん〜、他に、テストすることって、無い、よね?
よし。


お〜るおk。