FriendモデルのAASM対応とか、そんな感じ。

イヤ、なんか、もう、ね?
書くのが面倒になってきたwww


つうか、ね?
クリスマスを挟んで、FriendモデルをAASMに対応させて、「友達になろうぜ」メッセージを送れるようにして、受け取れるようにして、とかやってたんだけど、さ。


「おかしい。なんでstateが機能しないんだろう?」ってハマりにハマってたら、実は、Messageオブジェクトにstate付けようとしてました、とかwww


なんか、もう、ね?


あと、「ジョー・ブラックをよろしく」みたりとかwww


つうか、変わりすぎていて、ここに書くのも、もう、疲れたよパトラッシュ...
何だかとても眠いんだ...


とりあえず、AASMに関しては、毎度のごとく、ザリガニさんを参考に。

お世話になっております。


で、FriendモデルのAASM対応。
vendor/plugins/restful_authentication/lib/authorization/aasm_role.rbから、ごっそりコードを抜いて、以下のように書き換えて、friends_helper.rbとして、使っちゃいます。。
app/helpers/user/friends_helper.rb

module User::FriendsHelper
  module FriendsAasmRoles
    unless Object.constants.include? "STATEFUL_ROLES_CONSTANTS_DEFINED"
      STATEFUL_ROLES_CONSTANTS_DEFINED = true # sorry for the C idiom
    end
    
    def self.included( recipient )
      recipient.extend( StatefulRolesClassMethods )
      recipient.class_eval do
        include StatefulRolesInstanceMethods
        include AASM

        aasm_column :state
        
        aasm_initial_state :initial => :passive

        aasm_state :passive
        aasm_state :asked
        aasm_state :was_invited
        aasm_state :accepted,    :enter => :do_make_friendship
        aasm_state :denied
        aasm_state :deleted,     :enter => :do_delete_friendship

        aasm_event :ask  do
          transitions :from => :passive, :to => :asked
        end

        aasm_event :be_invited do
          transitions :from => :asked, :to => :was_invited
        end

        aasm_event :accept do
          transitions :from => :was_invited, :to => :accepted
        end

        aasm_event :deny do
          transitions :from => :was_invited, :to => :denied
        end

        aasm_event :delete do
          transitions :from => [:accepted, :denied], :to => :delete
        end
      end
    end

    module StatefulRolesClassMethods
    end # class methods

    module StatefulRolesInstanceMethods
      # Returns true if the user has just been made friendship.
      def recently_made_friendship?
        @made_friendship
      end
      def do_delete_friendship
        self.deleted_at = Time.now.utc
      end

      def do_make_friendship
        @activated = true
        self.made_friendship_at = Time.now.utc
        self.deleted_at = nil
      end
    end # instance methods
  end
end


んで、Friendモデル。
app/models/friend.rb

+  include User::FriendsHelper::FriendsAasmRoles
+
   belongs_to :asked_to,   :foreign_key => :was_invited_user_id,
                                 :class_name => "User"
   belongs_to :was_invited_from, :foreign_key => :asked_user_id,
(略)
   def self.friendships(user)
     friends = user.asked_friends | user.was_invited_friends
   end
+
+  def self.has_friendship?(user, friend)
+    friends = user.asked_friends | user.was_invited_friends
+    if friends.include?(friend)
+      friendship = Friend.find(:first, :conditions => { :asked_user_id => [user.id, friend.id],
+                                                        :was_invited_user_id => [user.id, friend.id]
+      })
+      return {:state => friendship.state,
+              :asked_user_id => friendship.asked_user_id,
+              :was_invited_user_id => friendship.was_invited_user_id 
+      }
+    else
+      return false
+    end
+  end

has_friendship?メソッドを作ったよ。
誘った/誘われた実績がある場合、stateと誘ったヤツの:idと誘われたヤツの;idを返して、実績が無い場合は、falseを返す。
なんか、あんまり「?」じゃない気もするけど、まあ、ヨシとするwww


つうか、submitアクション、なんかコードひどいなwww
もうちょっと、完結に書けそうなのに、ね?


次は、user/friends_controller.rb。
app/controllers/user/friends_controller.rb

(略)
+  def add
+    @user = User.find(params[:id])
+    if Friend.has_friendship?(current_user, @user)
+      flash[:notice] = "You are already have friendship with #{@user.nickname}"
+      redirect_back_or_default(user_profiles_path)
+    end
   end
 
+  def submit
+    @user = User.find(params[:id])
+    friendship = Friend.has_friendship?(current_user, @user)
+    if friendship
+      case friendship[:state]
+      when "asked"
+        flash[:notice] = "訊いてる最中やん"
+      when "was_invited"
+        flash[:notice] = "訊かれてる最中やん"
+      when "accepted"
+        flash[:notice] = "もう友達やん"
+      when "denied"
+        flash[:notice] = "断られとるやん"
+      when "deleted"
+        flash[:notice] = "おらんようになっとるやん。"
+      end
+    else
+      @message = Message.new(params[:message])
+      @message.message_type_id = MessageType.find_by_name(APP_CONFIG["message_type"]["be_friend"]).id
+      @message.sender_id = current_user.id
+      @message.reciever_id = params[:id]
+      @message.save if @message && @message.valid?
+      @friendship = Friend.new
+      @friendship.asked_user_id = current_user.id
+      @friendship.was_invited_user_id = params[:id]
+      @friendship.ask!
+      if @message && @message.valid?
+        flash[:notice] = "We are transmiting the message that you want to make friends with #{@user.nickname}"
+      end
+    end
+    if flash[:notice]
+      redirect_to(user_profiles_path)
+    else
+      flash[:notice] = "We couldn't send that message to #{@user.nickname}, sorry.  Please try again, "
+      render(:action => "add")
+    end
+  end

   def destroy
     
   end

addアクションとsubmitアクションを作ったよ。
それぞれ、友達になろうぜメッセージの作成と、友達になろうぜメッセージの送信 with Friendオブジェクトのstateの設定。


んで、ルーティングの変更。
config/routes.rb

   map.namespace :user do |user|
     user.resources :profiles
-    user.resources :friends
+    user.resources :friends, :member => { :add      =>  :get,
+                                          :submit     =>  :post
+    }
   end

あと、結構、スキーマ変更している。
migrateファイルを直接書き換えたりと醸してるんで、面倒だから、現状のスキーマ貼っとくwww
db/schema.rb

# This file is auto-generated from the current state of the database. Instead of editing this file, 
# please use the migrations feature of Active Record to incrementally modify your database, and
# then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
# to create the application database on another system, you should be using db:schema:load, not running
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 20081221091222) do

  create_table "friends", :force => true do |t|
    t.integer  "asked_user_id",                              :null => false
    t.integer  "was_invited_user_id",                        :null => false
    t.string   "state",               :default => "passive", :null => false
    t.datetime "made_friendship_at"
    t.datetime "deleted_at"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "message_types", :force => true do |t|
    t.string   "name",        :limit => 40, :null => false
    t.text     "description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "messages", :force => true do |t|
    t.integer  "message_type_id",                        :null => false
    t.integer  "sender_id",                              :null => false
    t.integer  "reciever_id",                            :null => false
    t.string   "subject",                                :null => false
    t.text     "body",                                   :null => false
    t.string   "senders_state",   :default => "passive", :null => false
    t.string   "reciever_state",  :default => "passive", :null => false
    t.datetime "sent_at"
    t.datetime "recieved_at"
    t.datetime "deleted_at"
  end

  create_table "roles", :force => true do |t|
    t.string "name"
    t.text   "description"
  end

  create_table "roles_users", :id => false, :force => true do |t|
    t.integer "role_id"
    t.integer "user_id"
  end

  add_index "roles_users", ["role_id"], :name => "index_roles_users_on_role_id"
  add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"

  create_table "users", :force => true do |t|
    t.string   "email",                     :limit => 100
    t.string   "crypted_password",          :limit => 40
    t.string   "salt",                      :limit => 40
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "remember_token",            :limit => 40
    t.datetime "remember_token_expires_at"
    t.string   "activation_code",           :limit => 40
    t.datetime "activated_at"
    t.string   "state",                                    :default => "passive"
    t.datetime "deleted_at"
    t.string   "nickname",                  :limit => 100, :default => ""
    t.string   "family_name",               :limit => 100, :default => ""
    t.string   "middle_name",               :limit => 100, :default => ""
    t.string   "given_name",                :limit => 100, :default => ""
  end

end


つうか、ここに書いていることを読み返して、オレ、ちゃんともう一回作れるのかね?www
なんか、すんげえ欠落している気がするんですけどwwwwww