Jan 2025【日本東北】溫泉三昧之旅③ 在大雪飄落的雪國,追尋秘湯之宿與極上美食(宮城縣~鹽釜水產市場的美味海鮮丼&中之沢溫泉)

圖片
早上退房後,請旅館幫忙叫了兩台計程車前來載我們前往白石藏王車站。當我們在白石藏王站下車時,雪花翩翩起舞,令人著迷。眼前,藏王連峰巍峨聳立,山頂覆蓋著皚皚白雪,在陽光的照耀下閃閃發光,宛如一條銀白色的巨龍,盤踞在天際線上。 我佇立在車站前,靜靜地欣賞著這壯麗的景色。 藏王連峰 的雪峰,層巒疊嶂,綿延不絕,展現出大自然的鬼斧神工。山坡上的樹木,有的被白雪完全覆蓋,形成一片片雪白的森林;有的則只在枝頭點綴著雪花,像是穿上了精緻的銀色花邊。 進入車站內,舒適的等候區讓人暫時躲避寒冷,而迷人的木芥子娃娃展示則吸引著我的目光。這些並不是普通的娃娃;它們是「鳴子木芥子」,以其獨特的工藝和歷史而聞名,與這個地區有著深深的交織。 我很好奇,於是深入研究了他們的故事。這一切開始於幾個世紀前,在江戶時代的東北地區中心。人們認為,木芥子娃娃的起源與「木芥子屋」有關,木芥子屋是技藝精湛的木工,專門製作木製物品。 這些工匠居住在東北各地的溫泉村,他們在寧靜的冬季運用自己的技藝製作出這些樸素而優雅的娃娃。 最早的木芥子被稱為“傳統木芥子”,是由東北地區溫泉村的木芥子匠人製作的。 每個地區都形成了自己獨特的風格,具有獨特的頭部形狀、身體圖案和繪畫技巧。 這些娃娃不僅僅是玩物;它們被賦予了更深刻的含義,通常被用作感情的象徵或紀念品。 隨著時間的推移,木芥子娃娃的流行範圍擴展到了溫泉村之外。 到了20世紀中葉,「創意木芥子」開始出現,展現出更廣泛的設計和藝術表現。 這些當代木芥子通常具有複雜的細節、鮮豔的色彩和創新的形式,反映了創作者不斷發展的藝術性。 如今,木芥子娃娃被視為日本民間藝術的象徵,體現了工匠精神和傳統。 它們讓我愉快地回憶起穿越東北的旅程,那是一個歷史與創造力交織的地區。 在車站等車時,我偶然看到一塊醒目的紅色看板,上面寫著斗大的標題「感受烽火歲月,造訪真田幸村的故鄉」,原來宮城縣的由利本莊市、白石市和藏王町都與戰國時代的名將真田幸村有著深厚的淵源!看來我的宮城之旅,除了享受自然風光,還可以來一趟歷史巡禮呢! 看板上詳細介紹了這三個地方與真田家的關係: 由利本莊市似乎是真田幸村女兒「阿梅」的夫家所在地。阿梅嫁給了本莊藩的藩主,並在此度過餘生。看板上還提到,當地保留著阿梅的墓地、牌位和一些她生前使用的物品,感覺可以感受到這位歷史人物的生活軌跡呢! 白石市則是真田幸村的次女「阿菖蒲」的出嫁之...

Integrating Facebook Connect with your Rails Applications

Facebook Connect is a set of APIs from Facebook that enable Facebook members to log onto third-party websites, applications, mobile devices and gaming systems with their Facebook identity. While logged in, users can connect with friends via these mediums and post information and updates to their Facebook profile. Developers can use these services to help their users connect and share with their Facebook friends on and off of Facebook and increase engagement for their website or application.

Originally unveiled during Facebook’s developer conference, F8, in July 2008, Facebook Connect became generally available in December 2008. According to an article from The New York Times, "Some say the services are representative of surprising new thinking in Silicon Valley. Instead of trying to hoard information about their users, the Internet companies (including Facebook, Google, MySpace and Twitter) all share at least some of that data so people do not have to enter the same identifying information again and again on different sites."

Windows Live服務整合Facebook Connect功能的畫面:


Facebook Connect是Facebook在2008年推出的功能,推出後馬上被許多大中小型網站所使用。透過Facebook Connect,用戶將可以在整個網路上使用Facebook的身份驗證資料,包括使用Facebook帳戶登入/註冊第三方網站,以及在其他網站分享他們的頭像照片、名稱、照片、朋友、群組、活動以及其他的資訊。這個是以前所做的東西,但Facebook已經在今年推出了新版的Open Graph API,若打算實作這個部份的話,建議還是使用新版的API會比較可靠!

Facebook Connect
http://developers.facebook.com/connect.php

Facebook Platform Wiki
http://en.wikipedia.org/wiki/Facebook_Platform


下面是實作Facebook Connect in Rails Application的過程:

1.首先我們需要給Rails project安裝Facebooker Plugin:
$ script/plugin install http://github.com/mmangino/facebooker/tree/master
安裝新版的facebooker插件必須將Rails升級到2.2版本以上.

2.你需要在Facebook註冊一個Developer測試帳戶,或是從下面網址讓你現有的Facebook帳戶成為Facebook Platform Developer Test Accounts(開發應用程式用的測試帳戶):
http://www.facebook.com/developers/become_test_account.php

登入Facebook Developer頁面註冊你的應用程式:
http://www.facebook.com/developers

步驟1. Add the Developer Application.
步驟2. Create a New Facebook Application.
步驟3. Update the Facebook Application settings to point to your publicly available host.

Example settings(假設域名是:http://www.example.com):

Authentication Tab:
  Enter Post-Authorize Callback URL, e.g. http://www.example.com/fb/post_authorize
  Canvas Tab:
Enter Canvas Page URL, e.g. run_example_com
Enter Canvas Callback URL, e.g. http://www.example.com/fb/connect
  Connect Tab:
Enter Connect URL, http://www.example.com/fb/connect
  Advanced Tab:
Set Application Type as Web.

將facebooker plugin裡的facebooker.yml文件放在/config目錄下,並編輯其內容:

Set api_key, secret_key, canvas_page_name (copy the last part of the Canvas Page URL from the Canvas tab), callback_url (that's Canvas Callback URL from FB settings), and set set_asset_host_to_callback_url to false.

下面是一個facebooker.yml範例內容:
development:
api_key: 1ad9f4ed4d40814d59e6ba8b4c538969
secret_key: 6522547e39322c7f8c03dc9cb40b2320
canvas_page_name: rails_demo_site
callback_url: http://www.example.com:3003/fb/connect/
pretty_errors: true
set_asset_host_to_callback_url: false
view raw facebooker.yml hosted with ❤ by GitHub

然後執行xd_receiver generator來產生cross domain scripting bridge,用來讓你的應用程式可以和Facebook溝通:

$ script/generate xd_receiver

預設之下它會在/public目錄下建立xd_receiver.html和xd_receiver_ssl.html兩個檔案,我們將它們放置到/public/fb/connect目錄下,因為這個路徑會對映到我們稍候建立的FbController的connect方法中,而我們也會在/config/route.rb中定義這個路徑。

接下來將facebooker plugin目錄下的facebooker.js複製到/public/javascript目錄下,並新增一個facebook_require.js檔案,內容如下:
FB_RequireFeatures(["XFBML"], function()
{
FB.Facebook.init(window.api_key, window.xd_receiver_location);
FB.Facebook.get_sessionState().waitUntilReady(function() { } );
});

編輯/public/javascript/application.js新增下面內容:
/*
* Ensure Facebook app is initialized and call callback afterward
*
*/
function ensure_init(callback) {
if(!window.api_key) {
window.alert("api_key is not set");
}
if(window.is_initialized) {
callback();
} else {
FB_RequireFeatures(["XFBML", "CanvasUtil"], function() {
FB.FBDebug.logLevel = 4;
FB.FBDebug.isEnabled = true;
// xd_receiver.php is a relative path here, because The Run Around
// could be installed in a subdirectory
// you should prefer an absolute URL (like "/xd_receiver.php") for more accuracy
FB.Facebook.init(window.api_key, window.xd_receiver_location);
window.is_initialized = true;
callback();
});
}
}
/*
* "Session Ready" handler. This is called when the facebook
* session becomes ready after the user clicks the "Facebook login" button.
* In a more complex app, this could be used to do some in-page
* replacements and avoid a full page refresh. For now, just
* notify the server the user is logged in, and redirect to home.
*
* @param link_to_current_user if the facebook session should be
* linked to a currently logged in user, or used
* to create a new account anyway
*/
function facebook_button_onclick() {
ensure_init(function() {
FB.Facebook.get_sessionState().waitUntilReady(function() {
var user = FB.Facebook.apiClient.get_session() ?
FB.Facebook.apiClient.get_session().uid :
null;
// probably should give some indication of failure to the user
if (!user) {
return;
}
// The Facebook Session has been set in the cookies,
// which will be picked up by the server on the next page load
// so refresh the page, and let all the account linking be
// handled on the server side
// This could be done a myriad of ways; for a page with more content,
// you could do an ajax call for the account linking, and then
// just replace content inline without a full page refresh.
//refresh_page();
window.location = window.facebook_authenticate_location;
});
});
}
/*
* Do a page refresh after login state changes.
* This is the easiest but not the only way to pick up changes.
* If you have a small amount of Facebook-specific content on a large page,
* then you could change it in Javascript without refresh.
*/
function refresh_page() {
window.location = '/';
}
function logout() {
window.location = '/logout';
}
/*
* Show the feed form. This would be typically called in response to the
* onclick handler of a "Publish" button, or in the onload event after
* the user submits a form with info that should be published.
*
*/
function facebook_publish_feed_story(form_bundle_id, template_data) {
// Load the feed form
FB.ensureInit(function() {
FB.Connect.showFeedDialog(form_bundle_id, template_data);
//FB.Connect.showFeedDialog(form_bundle_id, template_data, null, null, FB.FeedStorySize.shortStory, FB.RequireConnect.promptConnect);
// hide the "Loading feed story ..." div
// ge('feed_loading').style.visibility = "hidden";
});
}
view raw application.js hosted with ❤ by GitHub

編輯app/vews/layout/application.html.erb新增內容:
<%= javascript_include_tag 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php' %>
<%= javascript_tag "window.api_key = '#{Facebooker.api_key}';" %>
<%= javascript_tag "window.xd_receiver_location = '#{ENV['XD_RECEIVER_LOCATION']}';" %>
<%= javascript_tag "window.facebook_authenticate_location = '#{ENV['FACEBOOK_AUTHENTICATE_LOCATION']}';" %>
<%= javascript_include_tag 'facebook_require' %>

我們還要在適當的樣板中新增一個藉由Facebook Session登入的"登出"連結,用來區別和一般帳戶登入的不同,點擊'從Facebook登出'將會刪除現階段的Facebook Session並將使用者導向/logout來登出網站
<%- if facebook_user -%>
<%= link_to_function '從Facebook登出', 'FB.Connect.logout(function() {logout()})' %>
<%- else -%>
<%= link_to_unless_current '登出', '/account/logout', :method => :post %>
<%- end -%>

編輯/config/environment.rb,新增環境變數:
ENV['XD_RECEIVER_LOCATION'] = "/fb/connect/xd_receiver.html"
ENV['FACEBOOK_AUTHENTICATE_LOCATION'] = "/fb/authenticate"
view raw environment.rb hosted with ❤ by GitHub


典型的方式是使用網站資料庫裡現有的Users資料表中的DB Record來和Facebook帳戶整合, 我們將在users table中新增fb_uid(facebook uid)和email_hash(to contain a hashed version of the user's email address)欄位。

A typical case for integration is to add Facebook Connect as an alternative way of authenticating for existing users. To achieve this, add fields fb_uid (facebook uid) and email_hash (to contain a hashed version of the user's email address) to the users table.

接下來新增一個Run Publisher模型:
$ script/generate model RunPublisher

Publishing is handled by the RunPublisher class in app/models/run_publisher.rb. Every feed template needs to be registered with Facebook before it can be used and this is done via migrations.

編輯/app/models/run_publisher.rb的內容:
class RunPublisher < Facebooker::Rails::Publisher
def self.new_run_template_id
Facebooker::Rails::Publisher::FacebookTemplate.find_by_template_name('RunPublisher::new_run').bundle_id
end
def new_run_template
one_line_story_template "{*actor*} says {*status*}."
end
end

然後建立新的Database遷移檔:
$ script/generate migration CreateFacebookTemplates

編輯/db/migrate/xxxxx_create_facebook_templates.rb遷移檔內容:
class CreateFacebookTemplates < ActiveRecord::Migration
def self.up
create_table :facebook_templates, :force => true do |t|
t.string :template_name, :null => false
t.string :content_hash, :null => false
t.string :bundle_id, :null => true
end
add_index :facebook_templates, :template_name, :unique => true
print "Cleaning up any old templates ..."
Facebooker::Rails::Publisher::FacebookTemplate.destroy_all
puts " Done!"
RunPublisher.register_all_templates
puts "\nFinished registering all templates."
end
def self.down
drop_table :facebook_templates
end
end

然後還需要建立一個遷移檔,在users資料表添加一些新的欄位:
$script/generate migration AddFacebookConnectToUsers

編輯/db/migrate/xxxxx_add_facebook_connect_to_users.rb內容:
class AddFacebookConnectToUsers < ActiveRecord::Migration
def self.up
add_column :users, :fb_uid, :integer, :default => 0
add_column :users, :fb_password, :string
add_column :users, :email_hash, :string, :limit => 64, :null => true
end
def self.down
remove_column :users, :fb_uid
remove_column :users, :email_hash
end
end

最後執行rake db:migrate建立資料表!

接下來編輯/config/route.rb新增下面的路徑映射:
map.connect 'connect', :controller => 'fb_connect', :action => 'connect'
map.connect '/fb/:action', :controller => 'fb_connect'
view raw routes.rb hosted with ❤ by GitHub

在/bin目錄下新增fb_preconnect.rb內容如下:
require File.dirname(__FILE__) + '/../config/environment'
# this script sends all users to fb connect in order to preconnect them, in batches of 1,000
id = 1
window = 1000
max_id = User.maximum :id
while id < max_id
puts "Processing user ids from #{id}"
users = User.find(:all, :conditions => ['users.id >= ? and email is not null', id], :limit => window)
# generate email hash
users.each do |user|
user.email_hash
user.save
end
i = 0
begin
Facebooker::Session.create.post('facebook.connect.registerUsers', :accounts => users.inject([]) {|ar, user| ar << {:email_hash => user.email_hash, :account_id => user.id}}.to_json)
rescue
i += 1
retry if i < 3
end
id = users.last.id + 1
end

接下來在/bin目錄下新增register_templates.rb內容如下:
require File.dirname(__FILE__) + '/../config/environment'
print "Cleaning up any old templates ..."
Facebooker::Rails::Publisher::FacebookTemplate.destroy_all
puts " Done!"
puts
RunPublisher.register_all_templates
puts
puts "Finished registering all templates."

現在我們可以執行 script bin/fb_preconnect.rb 來預先連結資料庫中的所有使用者,這樣將能夠讓Facebook知道我們資料庫中的使用者可能會在將來使用Facebook Connect連結他們的帳戶。Facebook會預先連結使用者的 email_hash 來配對帳號。若不執行preconnect動作,Facebook將不會去包含 email hash 的值,將來使用者過Facebook Connect連結時,將需要輸入他們的Email地址!

稍候我們在/app/models/user.rb中建立的after_create callback可以讓將來任何新建立的使用者帳號都會自動和Facebook去做預先連結。

藉由Users資料表中的 fb_uid 欄位,使用者將可以透過正常的登入機制(帳號/密碼) 或是Facebook Connect 按鈕來登入,而我們會在/app/controllers/fb_connect_controller.rb建立Facebook Connect主要的驗證機制。


現在新增一個FBConnect Controller並編輯其內容如下:
$ script/generate controller FbConnect
class FbConnectController < ApplicationController
def authenticate
@facebook_session = Facebooker::Session.create(Facebooker.api_key, Facebooker.secret_key)
logger.debug "facebook session in authenticate: #{facebook_session.inspect}"
redirect_to @facebook_session.login_url
end
def connect
begin
secure_with_token!
session[:facebook_session] = @facebook_session
logger.debug "facebook session in connect: #{facebook_session.inspect}"
if facebook_user
if user = User.find_by_fb_uid(facebook_user.uid)
self.logged_in_user = user
return redirect_to('/')
end
# not a linked user, try to match a user record by email_hash
facebook_user.email_hashes.each do |hash|
if user = User.find_by_email_hash(hash)
user.update_attribute(:fb_uid, facebook_user.uid)
self.logged_in_user = user
return redirect_to('/')
end
end
# joining facebook user, send to fill in username/email to create db record
return redirect_to(:controller => 'users', :action => 'new', :fb_user => 1)
end
# facebook quite often craps out and gives us no data
rescue Curl::Err::GotNothingError => e
return redirect_to(:action => 'authenticate')
# it seems sometimes facebook gives us a useless auth token, so retry
rescue Facebooker::Session::MissingOrInvalidParameter => e
return redirect_to(:action => 'authenticate')
end
render(:nothing => true)
end
# callbacks, no session
def post_authorize
if linked_account_ids = params[:fb_sig_linked_account_ids].to_s.gsub(/\[|\]/,'').split(',')
linked_account_ids.each do |user_id|
if user = User.find_by_id(user_id)
user.update_attribute(:fb_uid, params[:fb_sig_user])
end
end
end
render :nothing => true
end
end

下面是我們的FbConnect Controller處理Facebook Session Login的簡單流程圖:


在Application Controller新增方法,用來處理Facebook Session以及Session Expired:
def facebook_session
session[:facebook_session]
end
def facebook_user
(session[:facebook_session] && session[:facebook_session].session_key) ? session[:facebook_session].user : nil
end
rescue_from Facebooker::Session::SessionExpired do
clear_facebook_session_information
clear_fb_cookies!
reset_session
redirect_to index_url
end
view raw application.rb hosted with ❤ by GitHub

然後需要修改用來處理登入驗證機制的/lib/login_system.rb的內容:
def self.included(base)
base.send :helper_method, :logged_in_user, :is_logged_in?, :facebook_user if base.respond_to? :helper_method
end
#將session[:facebook_session] = nil加到logout_keeping_session!方法中
def logout_keeping_session!
@logged_in_user.forget_me if @logged_in_user.is_a? User
@logged_in_user = false
kill_remember_cookie!
session[:user_id] = nil
session[:facebook_session] = nil
end
view raw login_system.rb hosted with ❤ by GitHub

接下來要修改/app/controllers/account_controller.rb中用來處理登出的logout方法:
def logout
if request.post? or facebook_user
logout_killing_session!
flash[:notice] = "您已經成功登出網站"
redirect_to login_url
else
flash[:notice] = "請用正常的方式登出網站"
redirect_to index_url
end
end

登出Rails網站並同時登出Facebook


接下來修改Users Controller中的New和Create方法(這是用來建立使用者的):
def new
@title = "註冊 #{app_name} 帳戶 | #{app_name}"
@user = User.new
if is_logged_in? || (params[:fb_user] && !facebook_user)
return redirect_to('/')
end
end
def create
@title = "註冊 #{app_name} 帳戶 | #{app_name}"
@user = User.new(params[:user])
@check = params[:check]
send_mail = !global_prefs.nil? && global_prefs.email_verifications?
#If signup with Yahoo! ID or Twitter OAuth
return unless request.post?
if (@user.yahoo_userhash || @user.twitter_id) != nil
@user.hashed_password = ""
# joining via FB connect: link to FB account and set a random password
elsif params[:fb_user]
return redirect_to('/') unless facebook_user
@user.fb_uid = facebook_user.uid
@user.hashed_password = ""
end
if @check
if verify_recaptcha(@user) && @user.save!
if params[:fb_user] || @user.twitter_id != nil || !send_mail
@user.activate
self.logged_in_user = @user
redirect_to index_url
flash[:notice] = "#{@user.f},歡迎!你的帳號現在已成功建立。"
else
UserNotifier.deliver_signup_notification(@user)
end
elsif @user.identity_url
render :action => 'fillup'
else
@user.clear_password!
render :action => 'new'
end
else
@user.clear_password!
flash[:error] = "你必須填滿所有的欄位。"
render :action => 'new'
end
rescue ActiveRecord::RecordInvalid
render :action => 'new'
end

在new方法添加這些過濾內容是為了防止使用者直接在網址攔輸入fb_user=1的參數來欺騙應用程式,正確的作法是必須透過Application_Controller中的facebook_user方法來驗證使用者是真正透過Facebook Session來註冊帳號。我們同樣也可以在create方法中添加這條過濾!

然後編輯User Model內容,修改password_required?方法:
def password_required?
return false if self.hashed_password.blank? && self.is_facebook_user?
return false if self.hashed_password.blank? && self.yahoo_userhash != nil
return false if self.hashed_password.blank? && self.twitter_id != nil
!self.password.blank? || !self.current_password.blank? || !self.password_confirmation.blank?
end
#並新增下面的新方法:
# Facebook Connect Methods
def is_facebook_user?
fb_uid > 0
end
def email_hash
if !(h = read_attribute(:email_hash))
h = write_attribute(:email_hash, build_email_hash(email))
end
return h
end
def email=(email)
self.email_hash = build_email_hash(email)
write_attribute(:email, email)
end
def register_with_facebook
Facebooker::Session.create.post('facebook.connect.registerUsers', :accounts => [{:email_hash => email_hash, :account_id => id}].to_json)
end
def before_update
# Re-register with Facebook if email address changed
if !new_record? && email_changed?
register_with_facebook
end
end
view raw user.rb hosted with ❤ by GitHub

上面的before_update是為了在使用者變更Email地址之後,建立新的Facebook Session和變更email_hash的值。其中的email_changed?是在Rails 2.1版本之後開始內建的方法,可以直接調用
def after_create
# Register with Facebook when a new user record is created
register_with_facebook
end
private
def build_email_hash(email)
str = email.strip.downcase
"#{Zlib.crc32(str)}_#{Digest::MD5.hexdigest(str)}"
end
view raw user.rb hosted with ❤ by GitHub

接下來修改/app/views/users/new.html.erb視圖的內容:
<% unless params[:fb_user] || @user.yahoo_userhash || @user.twitter_id %>
<div class="form_row">密碼:<em>(最少須包含六位數,數字加字母的組合更好)</em><br><%= f.password_field :password,
:size => User::PASSWORD_SIZE, :maxlength => User::PASSWORD_MAX_LENGTH,
:class => "validate['required','length[6,-1]','alphanum'] text-input" -%><br>
<small>Note: Email will not be publicly displayed</small></div>
<div class="form_row">確認密碼:<br><%= f.password_field :password_confirmation,
:size => User::PASSWORD_SIZE, :maxlength => User::PASSWORD_MAX_LENGTH,
:class => "validate['confirm[password]'] text-input" -%></div>
<% end %>
<% if params[:fb_user] %>
<%= hidden_field_tag(:fb_user, 1) %>
view raw new.html.erb hosted with ❤ by GitHub

然後修改/app/views/users/edit.html.erb視圖,編輯密碼修改的欄位部份:
<% unless @user.hashed_password.blank? && (@user.is_facebook_user? || @user.yahoo_userhash || @user.twitter_id) %>
<div class="form_row">目前的密碼:<br><%= f.password_field :current_password,
:size => User::PASSWORD_SIZE, :maxlength => User::PASSWORD_MAX_LENGTH -%></div>
<% end %>
view raw edit.html.erb hosted with ❤ by GitHub

並在users的edit和show視圖中新增下面的判斷內容:
<% if @user.is_facebook_user? %>
<p>你已經連結至 Facebook 帳戶 <strong><a href="https://www.facebook.com/profile.php?id=<%= facebook_user.uid %>" target="_blank"><%= facebook_user.name %></a></strong></p>
<% else %>
<%= render :partial => '/shared/fbconnect_button' %>
<% end %>
view raw show.html.erb hosted with ❤ by GitHub

然後在/app/views/shared目錄下建立_fbconnect_button.html.erb和_fbpublish.html.erb兩個樣板檔:

其中_fbconnect_button.html.erb內容如下:
<fb:login-button v="2" onclick='facebook_button_onclick()'></fb:login-button>

另外_fbpublish.html.erb內容如下:
<p id="publish_fb_checkbox" style="<%= facebook_user ? '' : 'display:none' %>">
<%= image_tag('http://static.ak.fbcdn.net/images/icons/favicon.gif') %>
<%= check_box_tag(:publish_to_facebook, 0, true) %>
張貼訊息至我的 Facebook 塗鴉牆
</p>

然後將貼到需要添加Facebook登入按鈕的視圖頁面即可(如首頁,Signup頁面和Login頁面)


接下來我們可以編輯相關的視圖,讓透過Facebook Session登入的使用者可以在頁面上直接顯示他們的Facebook頭像圖片和Facebook用戶名稱(點擊圖片可以連結至他們的Facebook頁面),而不再是我們網站上的頭像圖片。

PS.從這邊開始的部份都是我自己的Rails Project的內容,看不懂的請不要亂複製到你的Project,我這裡只是提供一個概念作為參考!

首先修改users_helper.rb中的user_link方法:
def user_link(text, user = nil, html_options = nil)
if user.nil?
user = text
text = user.name
elsif user.is_a?(Hash)
html_options = user
user = text
text = user.name
end
if facebook_user && user == logged_in_user
link_to(h(facebook_user.name), profile_path(user), html_options)
else
link_to(h(text), profile_path(user), html_options)
end
end
view raw users_helper.rb hosted with ❤ by GitHub

然後修改users/_status_update.html.erb的視圖內容,這是使用者首頁的狀態發佈器。
<%- if facebook_user -%>
<fb:profile-pic uid="<%= facebook_user %>" size="square" facebook-logo="true" ></fb:profile-pic>
<%- else -%>
<%= image_link @user, :image => :tiny %></td>
<%- end -%>

接著修改users/_current_status.html.erb視圖:
<span><strong><%= facebook_user ? facebook_user.name : user.short_name %></strong></span>
<span id="current-status-text"><%= status %></span>

最後將下面內容加到/app/controllers/users/status_update_controller.rb的Create方法中:
@status_update.text.gsub!(facebook_user.name, '')
view raw temp hosted with ❤ by GitHub



另外我們還可以修改/app/views/wall_comments底下的_form.html.erb和_comment.html.erb視圖,讓透過Facebook Session登入的使用者可以在Profile頁面的塗鴉牆看到自己的Facebook頭像和名字:

修改/app/views/wall_comments/_form.html.erb視圖:
<table>
<tr>
<td rowspan="2">
<%- if facebook_user -%>
<fb:profile-pic uid="<%= facebook_user %>" size="square" facebook-logo="true" ></fb:profile-pic></td>
<%- else -%>
<%= image_link @user, :image => :tiny %></td>
<%- end -%>
<td></td>
</tr>
<tr>
<td>
<div id="comment-body" class="form_row">
<%= f.text_area :body, :value => '留言...', :id => 'comment-body-field', :rows => 2, :cols => 35 %>
</div>
</td>
<td id="submit-comment" class="row button">
<%= submit_tag "張貼內容", :class => "button" %>
</td>
<td id="progress-bar" style="display:none;" align="center">
<img src="/images/indicator_blue_small.gif" alt="progress bar">
</td>
</tr>
</table>
view raw _form.html.erb hosted with ❤ by GitHub

修改/app/views/wall_comments/_comment.html.erb視圖:
<div class="profile-image">
<%- if facebook_user && is_me?(comment.commenter) -%>
<fb:profile-pic uid="<%= facebook_user %>" size="square" facebook-logo="true" ></fb:profile-pic>
<%- else -%>
<%= image_link(comment.commenter, :image => :tiny) %>
<%- end -%>
<%= image_tag "icons/comment.png", :class => "icon" %>
</div>

OK搞定了!而其他需要顯示Facebook頭像的頁面也可以用同樣的邏輯來作修改,非常簡單!


接下來我們要將Rails網站裡面的一些功能和Facebook做進一步的整合,首先我們要將使用者首頁的狀態更新和Facebook塗鴉牆整合,讓使用者在網站上更新狀態時,訊息可以同時發佈到使用者的Facebook塗鴉牆上。

首先在users/status_update_controller.rb中新增一個fbpublish方法:
if params[:publish_to_facebook]
facebook_user.session.post 'facebook.stream.publish', :message => "#{@status_update.text}"
end

然後編輯/public/javascript/application.js新增下面的內容,其中的Ajax Request路徑會指向Users::StatusUpdatesController中的fbpublish方法,它會執行一些Ajax動作:
function permission_granted() {
$('fb_publish').childElements().each(function(item){
item.remove();
});
new Ajax.Request('/users/status_updates/fbpublish', {method: 'get'})
}
view raw application.js hosted with ❤ by GitHub

接著我們在users/status_update_controller.rb的Create方法中添加下面的內容:
if params[:publish_to_facebook]
facebook_user.session.post 'facebook.stream.publish', :message => "#{@status_update.text}"
end

然後在建立/app/views/shared目錄下建立_fbpublish.html.erb樣板:
<div id="publish_fb_checkbox" style="<%= facebook_user ? '' : 'display:none' %>">
<%= image_tag('http://static.ak.fbcdn.net/images/icons/favicon.gif') %>
<%= check_box_tag(:publish_to_facebook, 0, true) %>
同時張貼訊息到我的 Facebook 塗鴉牆上
</div>

並修改users/_status_update.html.erb樣板內容:
<div id="publish_fb_checkbox" style="<%= facebook_user ? '' : 'display:none' %>">
<%= image_tag('http://static.ak.fbcdn.net/images/icons/favicon.gif') %>
<%= check_box_tag(:publish_to_facebook, 0, true) %>
同時張貼訊息到我的 Facebook 塗鴉牆上
</div>

另外,視圖中jQuery的部份也需要修改:
jQuery(document).ready(function() {
jQuery('#status_update').val("你在想什麼?");
jQuery('#status_update').click(function(){
jQuery('#status_update').val("<%= facebook_user ? facebook_user.name + ' ' : @user.short_name + ' ' %>");
jQuery('#status-update-field').removeClass('status-update-dim');
jQuery('#status-update-field').addClass('status-update-lit');
jQuery("#submit-button").show();
});
jQuery("#status_update_form").submit(function() {
jQuery("#status-update-field").hide();
jQuery("#submit-button").hide();
jQuery("#progress-bar").show();
});
});
view raw jquery hosted with ❤ by GitHub


使用者尚未授權Facebook帳戶可以透過第三方網站張貼內容至Facebook塗鴉牆


授權Facebook帳戶畫面,授權之後我們的應用程式會去呼叫Users::StatusUpdatesController中的fbpublish方法執行Ajax動作。


已授權Facebook帳戶可以從第三方網站張貼內容至Facebook塗鴉牆


訊息已透過我們的應用程式發佈到使用者的Facebook塗鴉牆上


最後我們可以在使用者的首頁和個人檔案頁面顯示該使用者Facebook帳號上的朋友,首先在首頁和個人檔案頁面載入部份樣板:
<!-- If a facebook user, then show info about their friends -->
<%- if is_me?(@user) and facebook_user -%>
<%= render :partial => '/shared/fbfriends' %>
<%- end -%>
view raw fb_friends hosted with ❤ by GitHub

最後建立/app/views/shared/_fbfriends.html.erb樣板:
<h3>Facebook朋友</h3>
<% friends = facebook_user.friends_with_this_app %>
<% if friends.any? %>
<% friends.each do |friend| %>
<div class="left fb_friends">
<fb:profile-pic uid="<%= friend %>" size="square" facebook-logo="true" ></fb:profile-pic>
<span><a href="http://www.facebook.com/profile.php?id=<%= friend %>" target="_blank"><%= friend.name %></a></span>
</div>
<% end %>
<div class="clear"></div>
<span class="left">
<%= link_to "#{friends.count} 位朋友", user_friends_path(logged_in_user) %>
</span>
<span class="right">
<%= link_to "顯示全部", user_friends_path(logged_in_user) %>
</span>
<% else %>
<p>你在<%= app_name %>還沒有Facebook朋友,你可以
<%= link_to "邀請朋友", new_user_invite_path(logged_in_user) -%>使用Facebook帳戶來註冊<%= app_name %>。</p>
<% end %>




下面是一些Facebook Connect的相關資源以及Tutorial:

Facebook Connect on Facebook Developers
http://developers.facebook.com/connect.php

Using Ruby on Rails with Facebook Platform
http://wiki.developers.facebook.com/index.php/Using_Ruby_on_Rails_with_Facebook_Platform

Facebooker Tutorial
http://apps.facebook.com/facebooker_tutorial/

Tutorial for restful_authentication on Rails with Facebook Connect in 15 minutes
http://www.madebymany.co.uk/tutorial-for-restful_authentication-on-rails-with-facebook-connect-in-15-minutes-00523

Tutorial on developing a Facebook platform application with Ruby On Rails
http://www.liverail.net/articles/2007/6/29/tutorial-on-developing-a-facebook-platform-application-with-ruby-on-rails

Integrating Facebook Connect with Rails Applications
http://nws.applicake.com/blog/index.php/2009/07/02/integrating-facebook-connect-with-rails-applications/

Using Facebooker to make a Rails site with Facebook Connect (Part 1)
http://blog.moove-it.com/using-facebooker-to-make-a-rails-site-with-facebook-connect-part-1/

Using Facebooker to make a Rails site with Facebook Connect (Part 2)
http://blog.moove-it.com/using-facebooker-to-make-a-rails-site-with-facebook-connect-part-2/

Using Facebooker to make a Rails site with Facebook Connect (Part 3)
http://blog.moove-it.com/using-facebooker-to-make-a-rails-site-with-facebook-connect-part-3/

Rails app on Facebook Connect
http://www.rubyflow.com/items/1322

Star in a Porno with Facebook Connect and Rails
http://spongetech.wordpress.com/2008/11/17/star-in-a-porno-with-facebook-connect-and-rails/

How to Facebook-Connect a Rails app
http://passthehash.com/hash/2009/05/how-to-facebook-connect-your-rails-app.html

Getting Started with Facebooker
http://www.pathf.com/blogs/2008/07/getting-started-with-facebooker/

熱門文章

Jan 2025【日本東北】溫泉三昧之旅④ 在大雪飄落的雪國,追尋秘湯之宿與極上美食(福島~探訪豬苗代湖、磐梯山、會津若松城&千年古湯 蘆之牧溫泉)

May, 2024【新北瑞芳】四腳亭步道|漫步油桐花步道,踏訪時光痕跡:四腳亭砲台歷史尋幽之旅(順訪在地老店 橋頭排骨麵)

Feb 2023【台中和平】裡冷林道Off Road單車野營~順登谷關七雄之首八仙山!單車+野營+登山,三個願望一次滿足

Jan 2025【日本東北】溫泉三昧之旅② 在大雪飄落的雪國,追尋秘湯之宿與極上美食(仙台~品嚐極上米澤牛&奧羽的百年藥湯-鎌先溫泉)

台中【馨苑小料理】西區店|巷弄裡的人氣台菜店|米其林必比登推薦美食|提供合菜、個人套餐

Feb 2025【新竹尖石】凌空廊道起登,連走林相優美的煤源山、比麟山、尖石山(煤比尖連走)&紅磚美食坊吃山產&朝日溫泉民宿泡湯

Mar 2025【桃園復興】高遶溪古圳步道健行(第二期步道已完工,全長2.6公里)|隱藏版道地新疆料理~胡同彭家老舖新疆拉麵

Sep 3~4, 2021【烏來三大林道】未完成的「新北橫公路」~遠離塵世喧囂的西坑林道、桶後林道、內洞林道

Jan 2025【日本東北】溫泉三昧之旅① 在大雪飄落的雪國,追尋秘湯之宿與極上美食(秋田~探訪有日本溫泉界頂點之稱的秘湯乳頭溫泉鶴之湯)

Mar 2025【新竹五峰】油羅山森呼吸:擁抱原始柳杉林秘境之美(羅山林道第一登山口往返)

文章列表

Contact

名稱

以電子郵件傳送 *

訊息 *