Facebookアプリを作ってみましたシリーズ3 (Ruby on Rails + mogli + facebooker2編)

前回に続き、また新しいFacebookアプリをRubyで作りました。

アプリはこちら

今回は新感覚誕生日占いアプリです。
きっとビックリな結果が待っていると思います。ぜひ使ってみてください。
http://apps.facebook.com/butsumeticbirthday/

開発について

今回は前回とは別のFacebook SDKを使ってみました。


使ったFacebook SDKは、facebooker2mogliです。
この二つは一緒に使います。
mogliがRuby用のFacebookのGraph APIライブラリで、
facebooker2はmogli用のJavaScriptまわりの拡張といった感じでしょうか。


このライブラリは、koalaやfb_graphには無い、Facebookアプリ作成で躓きそうなところ(詳細はまた今度書きます)のサポートが含まれていて、
単なるGraphAPIライブラリではなくかなりイケていると思いました。


他、説明するのが面倒くさいのでソースそのまま貼っときますので、必要であれば勝手に見てください。
Ruby勉強中なのでイケてないところとかあったら教えてください)

ソース


application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  include Facebooker2::Rails::Controller
  before_filter :set_p3p_header_for_third_party_cookies
  include ApplicationHelper
end


pages_controller.rb

class PagesController < ApplicationController
  def home
    
    if current_facebook_user.nil? && params[:submit].nil?
      render :home
      return
    end
    
    if params[:submit].nil?
      current_facebook_user.fetch
      #04/01/1989
      @birthday = Date.strptime(current_facebook_user.birthday, "%m/%d/%Y")
      @gender = current_facebook_user.gender
    else
      date = params[:date]
      @birthday = Date.new(date["year"].to_i, date["month"].to_i, date["day"].to_i)
      @gender = params[:gender]
    end
    
    @past_butsumetic_birthdays = past_butsumetic_birthdays @birthday
    @rest_butsumetic_birthdays = rest_butsumetic_birthdays @birthday, @gender
    @next_rokuyou = rokuyou kyureki(get_next_birthday(@birthday))
    render :main
    return
    
  end
end


application_helper.rb

module ApplicationHelper
  
  def kyureki(d = Date.today)
    g = Gregorian.new(d.month, d.day, d.year)
    Kyureki.at(g.abs)
  end
  
  def rokuyou(d = nil)
    if d.nil?
      d = kyureki
    end
     (d.month + d.day) % 6
  end
  
  def rokuyou_label r = nil
    if r.nil?
      r = rokuyou
    end
    ['大安','赤口','先勝','友引','先負','仏滅'][r]
  end
  
  def past_count birthday
    now = Date.today
    count = 0
    while (birthday <=> now) < 0
      count = count + 1 if rokuyou(kyureki birthday) == 5
      birthday = birthday.next_year
    end
    count
  end
  
  def past_butsumetic_birthdays birthday
    now = Date.today
    bb = []
    while (birthday <=> now) < 0
      bb << birthday if rokuyou(kyureki birthday) == 5
      birthday = birthday.next_year
    end
    bb
  end
  
  def rest_count birthday, gender
    lifetime = get_lifetime(gender) + birthday.year
    next_birthday = get_next_birthday birthday
    count = 0
    while next_birthday.year <= lifetime
      count = count + 1 if rokuyou(kyureki next_birthday) == 5
      next_birthday = next_birthday.next_year
    end
    count
  end
  
  def rest_butsumetic_birthdays birthday, gender
    lifetime = get_lifetime(gender) + birthday.year
    next_birthday = get_next_birthday birthday
    bb = []
    while next_birthday.year <= lifetime
      bb << next_birthday if rokuyou(kyureki next_birthday) == 5
      next_birthday = next_birthday.next_year
    end
    bb
  end
  
  def get_next_birthday birthday
    now = Date.today
    birthday = Date.new(now.year, birthday.month, birthday.day)
    if (birthday <=> now) < 0
      birthday = birthday.next_year
    end
    birthday
  end
  
  def get_lifetime gender
    #参考 http://ja.wikipedia.org/wiki/%E5%9B%BD%E3%81%AE%E5%B9%B3%E5%9D%87%E5%AF%BF%E5%91%BD%E9%A0%86%E3%83%AA%E3%82%B9%E3%83%88
    if gender == "male"
      79
    elsif gender == "female" 
      86
    else
      raise "which? " + gender
    end
  end
  
  def get_age birthday, today = Date.today
    age = today.year - birthday.year
    return age -1 if birthday.month > today.month
    return age -1 if birthday.month == today.month && birthday.day > today.day
    return age
  end
end


application.html.erb

<!DOCTYPE html>
<html xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
  <title>ブツメティックバースデー</title>
  <%= stylesheet_link_tag :all %>
  <%= javascript_include_tag :all %>
  <%= csrf_meta_tag %>
	<meta property="og:type" content="website" />
	<meta property="og:title" content="ブツメティックバースデー" />
	<meta property="og:url" content="http://apps.facebook.com/butsumeticbirthday/" />
	<meta property="og:image" content="http://kissrobber.com/butsumeticbirthday/images/logo.png" />
	<meta property="fb:app_id" content="<%= Facebooker2.app_id %>" />
	<meta property="og:description" content="ブツメティックバースデーは新しい誕生日占いです。" />
	<meta name="author" content="http://iq148.com" />
	<link rel="canonical" href="http://apps.facebook.com/butsumeticbirthday/" />
	<link rel="shortcut icon" href="http://kissrobber.com/butsumeticbirthday/favicon.ico" />
</head>
<body>

<%= yield %>

<div id="fb-root"></div>
<script src="http://connect.facebook.net/ja_JP/all.js"></script>
<script>
  FB.init({
    appId  : '<%= Facebooker2.app_id %>',
    status : true,
    cookie : true,
    xfbml  : true
  });
  function login(){
	FB.login(function(response) {
	  if (response.session) {
	    location.href="http://kissrobber.com/butsumeticbirthday/";
	  } else {
	    
	  }
	}, {perms:'user_birthday'});
  }
  function feed(){
   FB.ui(
	   {
	     method: 'feed',
	     name: 'ブツメティックバースデー',
	     link: 'http://apps.facebook.com/butsumeticbirthday/',
	     picture: 'http://kissrobber.com/butsumeticbirthday/images/logo.png',
	     description: 'ブツメティックバースデーは新しい誕生日占いです',
	     actions: {'name':'powered by iq148.com', 'link':'http://iq148.com'}
	   });
  }
</script>
</body>
</html>


main.html.erb

<div id="message11" style="display:none;">
    <fb:like layout="button_count" href="http://apps.facebook.com/butsumeticbirthday/" colorscheme="dark">
    </fb:like>
    <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://apps.facebook.com/butsumeticbirthday/" data-text="ブツメティックバースデーは新しい誕生日占いです" data-count="horizontal" data-via="kissrobber" data-lang="ja">Tweet</a>
    <script type="text/javascript" src="http://platform.twitter.com/widgets.js">
    </script>
    <a href="http://b.hatena.ne.jp/entry/http://apps.facebook.com/butsumeticbirthday/" class="hatena-bookmark-button" data-hatena-bookmark-title="ブツメティックバースデー" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"/></a>
    <script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async">
    </script>
    <br/>
    <% if current_facebook_user.nil? %>
    <p>
        <a href="javascript:void(0);" onclick="login();">Facebookでログインして占う。(全ての機能を使う事ができます)</a>
    </p>
    <% else %>
    <p>
        <a href="javascript:void(0);" onclick="feed();">シェアする</a>
    </p>
    <% end %>
</div>
<p id="message1" style="display:none;">
    あなたの次の誕生日は仏滅で<%= if @next_rokuyou == 5 then "" else "はありません" end %>。
</p>
<p id="message2" style="display:none;">
    <%= if @next_rokuyou == 5 then "がんばってください。" else "よかったですね。" end %>。
</p>
<p id="message3" style="display:none;">
    ところで、あなたの過去を振り返ってみてください
</p>
<table border="1" width="250px" id="message4" style="display:none;">
    <% @past_butsumetic_birthdays.each do |past_birthday| %>
    <tr>
        <td width="200px">
            <%= past_birthday.strftime("%Y年%m月%d日") %><%= get_age(@birthday, past_birthday) %>歳
        </td>
        <td width="50px">
            <b>仏滅</b>
        </td>
    </tr>
    <% end %>
</table>
<p id="message5" style="display:none;">
    あなたは今まで仏滅の誕生日を<%= @past_butsumetic_birthdays.size %>回経験しました。
</p>
<p id="message6" style="display:none;">
    この先、死ぬまでにあと<%= @rest_butsumetic_birthdays.size %>回仏滅の誕生日を経験するかもしれません。
</p>
<table border="1" width="250px" id="message7" style="display:none;">
    <% @rest_butsumetic_birthdays.each do |rest_birthday| %>
    <tr>
        <td width="200px">
            <%= rest_birthday.strftime("%Y年%m月%d日") %><%= get_age(@birthday, rest_birthday) %>歳
        </td>
        <td width="50px">
            <b>仏滅</b>
        </td>
    </tr>
    <% end %>
</table>
<p id="message8" style="display:none;">
    これからの試練を乗り越えてください
</p>
<p id="message9" style="display:none;">
    Enjoy your Butsumetic Birthday!
</p>
<div id="message10" style="display:none;">
    <fb:like layout="button_count" href="http://apps.facebook.com/butsumeticbirthday/" colorscheme="dark">
    </fb:like>
    <a href="http://twitter.com/share" class="twitter-share-button" data-url="http://apps.facebook.com/butsumeticbirthday/" data-text="ブツメティックバースデーは新しい誕生日占いです" data-count="horizontal" data-via="kissrobber" data-lang="ja">Tweet</a>
    <script type="text/javascript" src="http://platform.twitter.com/widgets.js">
    </script>
    <a href="http://b.hatena.ne.jp/entry/http://apps.facebook.com/butsumeticbirthday/" class="hatena-bookmark-button" data-hatena-bookmark-title="ブツメティックバースデー" data-hatena-bookmark-layout="standard" title="このエントリーをはてなブックマークに追加"><img src="http://b.st-hatena.com/images/entry-button/button-only.gif" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;"/></a>
    <script type="text/javascript" src="http://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async">
    </script>
    <br/>
    <% if current_facebook_user.nil? %>
    <p>
        <a href="javascript:void(0);" onclick="login();">Facebookでログインして占う。(全ての機能を使う事ができます)</a>
    </p>
    <% else %>
    <p>
        <a href="javascript:void(0);" onclick="feed();">シェアする</a>
    </p>
    <% end %>
</div>
<script>
    window.fbAsyncInit = function(){
        $("#message1").fadeIn(3000, function(){
            $("#message2").fadeIn(3000, function(){
                $("#message3").fadeIn(3000, function(){
                    $("#message4").fadeIn(3000, function(){
                        $("#message5").fadeIn(3000, function(){
                            $("#message6").fadeIn(3000, function(){
                                $("#message7").fadeIn(3000, function(){
                                    $("#message8").fadeIn(3000, function(){
                                        $("#message9").fadeIn(3000, function(){
                                            $("#message10").fadeIn(3000, function(){
                                                $("#message11").fadeIn(500, function(){
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
        
    };
</script>