2016年4月24日 星期日

Published 凌晨3:25 by with 0 comment

Rails 抓取 Facebook 大頭照解析度 - 我在ALPHACamp 63天


大頭照預設大小有四種

http://graph.facebook.com/id/picture?type=small
http://graph.facebook.com/id/picture?type=square
http://graph.facebook.com/id/picture?type=large
http://graph.facebook.com/id/picture?type=normal

預設都是抓取 square, 但是不論放在手機或是網頁上~ 根本就是8bit時代的產物

所以在抓取檔案時要指定large (200x200)



手機API部分 :

app/model/user.rb,在picture加上 .type(large)

res = RestClient.get "https://graph.facebook.com/v2.4/me",  { :params => { :fields => "email,name,gender,picture.type(large)", :access_token => access_token } }
OmniAuth 部分:

config/initializers/devise.rb 之中 加上 :image_size => 'large'

config.omniauth :facebook, fb_config["facebook"]["app_id"], fb_config["facebook"]["secret"], :scope => 'public_profile,email', :info_fields => 'name,gender,email', :image_size => 'large'
對! 這樣就結束了...
Read More
      edit

2016年4月23日 星期六

Published 凌晨12:52 by with 0 comment

如何完成好簡報:簡報技巧教學(孫治華老師)- 我在ALPHACamp 62天




每一份簡報的背後都有目的以及想要傳達的理念, 但往往大家在各自的專業領域很強, 但是忽略了要如何表達, 對於簡報來說

專業價值 x 傳遞價值 = 市場價值

專業價值: 指的是你對自己能力的認知. 可能是80分

傳遞價值: 你的表達能力. 但這會是轉換率. 可能是 70%

市場價值: 對方接受的程度 依照上面來看, 只剩下: 56分 而已..

以往大家心目中的簡報都需要下面特質:

  1. 超美的背景圖
  2. 設計跟舒服的配色
  3. 演講天份
  4. 不斷的練習
  5. 背熟講稿
  6. 豐富的肢體動作

但這幾點卻不是最需要得重點

最重要的是 “溝通” 以及 ”心“

-簡報大略分三種-

a. 提案

在提案階段,溝通成為了重點. 若是老闆指派, 要明確知道簡報的目標, 以及對方的需求.
所以提案階段可以分成:

  1. 設定目標
  2. 選擇方案
  3. 執行重點
  4. 時程預算
  5. 人力資源

1,4,5 需要要求者明確定義, 或是用換位思考來確認對方想要什麼.

但回歸到2,3 這兩點卻是我們自己需要創造的.

b. 執行

當產品 or 活動, 開始執行時, 也需要產出進度報告. 需要的內容有:
  1. 執行規劃
  2. 進度報告
  3. 時間review
  4. 人力review

c. 結案

結案報告需要有這三大要素:
  1. 檢視目標
  2. 執行成效
  3. 未來規劃
所以在整個活動/專案開始之前, 獲得明確的方向最為重要. 與別人溝通, 或是提問可以參考:

彙整以下重點可以分成:
  1. 講稿式的投影片
  2. 錯字
  3. 太多的分類(沒有重點)
  4. 配色錯誤
  5. 數據註解太多
  6. 投影片數量過多
  7. 複雜的數據圖
  8. 動畫
製作簡報的工具有:
  1. ICON :工具 https://thenounproject.com/ (PNG 去背)(SVG 可以調顏色)
              工具 https://cloudconvert.com/ (拆解icon)
  2. PTT 樣板: http://www.pptfans.cn/


-簡報流成-


可以細分三大步驟

  1. 開場: 抓住聽者的目光
    (效益, 特色, 創意)
  2. 中段: 專業領域
    (技術, 個案, 數據)
  3. 結尾: 引響力
    (時程, 討論, 決策)
表達方式: 舉例

今天產品如果是行動電源 擁有 10000mAh的容量

文案可能是:

業界第一款 10000mAh 行動電源

進階版:

首款可以讓你充電10小時不間斷!

直述法:

讓你從台北坐車到墾丁, 電量不會減少!


-後記-


其實這篇的重點會是在於圖像的表達, 並非純文字稿.
但是... 今天就是發文不附圖XD




Read More
      edit

2016年4月22日 星期五

Published 凌晨3:18 by with 0 comment

Rails User 建立-3 (手機抓取FB資料, html抓取FB資料)- 我在ALPHACamp 61天

-概述-

手機取得的資料跟 web得到的有些不一樣

大頭照(手機: picture, Web: image)

手機
 user.fb_pic = auth.info.picture.data.url
web
 user.fb_pic = auth.info.image
性別(gender)

手機:
 user.gender = auth.info.gender
web:
 user.gender = auth.extra.raw_info.gender

再來就是取得的方式也不一樣

手機:  RestClint
Web: Devise+Omiauth

以下是作法:

-手機 API抓取FB資料 - 
(使用RestClient)



目前可以抓取的資料有 :

名子(name),性別(gender), 信箱(email),大頭照(picture)


1. app/model/user.rb 之中新增我們要抓得值: email, name, gender, picture


res = RestClient.get "https://graph.facebook.com/v2.4/me",  { :params => { :fields => "email,name,gender,picture.type(large)", :access_token => access_token } }

2. 在app/controllers/api_v1/auth_controller.rb 新增

def signup
success = false
#POST /api/v1/signup

....

 elsif params[:access_token]

   fb_data = User.get_fb_data( params[:access_token] )

     if fb_data
       auth_hash = OmniAuth::AuthHash.new({
         uid: fb_data["id"],
         info: {

           email: fb_data["email"],
           gender: fb_data["gender"],
           name: fb_data["name"],
           picture: fb_data["picture"]

         },
         credentials: {
           token: params[:access_token]
         }
       })

....

end
=> 透過這方法我們會得到 auth的 hash, 接下來要讀出裡面得值



我們可以在這邊利用 byebug 來看我們剛剛在auth得到什麼東西



大頭照會包在info.pirture.data.url裡面


3. app/model/user.rb  我們新增一個專屬於的 self.from_omniauth_api(auth) 
 (因為與html取得方式格式不一樣, 所以我們拆開來寫)
   <這邊沒有遵照 don't repeat yourself >

def self.from_omniauth_api(auth)
 # Case 1: Find existing user by facebook uid
 user = User.find_by_fb_uid( auth.uid )
 if user
    user.fb_token = auth.credentials.token
    user.save!
   return user
 end

 # Case 2: Find existing user by email
 existing_user = User.find_by_email( auth.info.email )
 if existing_user
   existing_user.fb_uid = auth.uid
   existing_user.fb_token = auth.credentials.token
   existing_user.save!
   return existing_user
 end

 # Case 3: Create new password
 user = User.new
 user.fb_pic = auth.info.picture.data.url
 user.fb_uid = auth.uid
 user.fb_token = auth.credentials.token
 user.email = auth.info.email
 user.password = Devise.friendly_token[0,20]
 user.fb_raw_data = auth
 user.gender = auth.info.gender
 user.username = auth.info.name

 user.save!
 return user
end

4. 再到app/controllers/api_v1/auth_controller.rb 得singup裡面修改

def singup
.
.
   user = User.from_omniauth_api(auth_hash)
. 
.
end




- html抓取FB資料 -
 (使用 Devise +omiauth)



跟FB 抓資料概念一樣, 要先設定我們要抓哪些資料

1. config/initializers/devise.rb

fb_config = Rails.application.config_for(:facebook)
  config.omniauth :facebook, fb_config["facebook"]["app_id"], fb_config["facebook"]["secret"], :scope => 'public_profile,email', :info_fields => 'name,gender,email', :image_size => 'large'
我們已經在上方第二步驟新增app/controllers/api_v1/auth_controller.rb

但是這邊大頭照所在的位置是不一樣的, 從API方式來的是picture

但是從html來的是image

但由於這邊picture是預設值, 所以我們不用在 auth_controller裡面

我們也可以用 byebug來確認我們得到的auth



=> 這次 gender 藏在 raw_info裡面


2. 在app/model/user.rb  的 self.from_omniauth(auth) 取出裡面的值 

 # Case 3: Create new password
 user = User.new
 user.fb_uid = auth.uid
 user.fb_token = auth.credentials.token
 user.email = auth.info.email
 user.password = Devise.friendly_token[0,20]
 user.fb_raw_data = auth
 user.gender = auth.extra.raw_info.gender
 user.username = auth.info.name
 user.fb_pic = auth.info.image
 user.save!
 return user


Read More
      edit

2016年4月20日 星期三

Published 凌晨1:49 by with 0 comment

Rails User 建立-2 (手機email註冊,隱藏yml,手機fb註冊) - 我在ALPHACamp 59天


1. 手機使用者註冊
(用 email / password 註冊)


這次專案的做法是使用Devise來管控使用者,

使用者可以在手機上註冊的觀念:

手機傳一個 POST JSON 給後端 後端寫入後回傳一個 authentication_token


a.  /app/controllers/api_v1/auth_controller.rb 新增

def signup
  #POST /api/v1/signup

  if params[:email] && params[:password]

    user = User.new(:email => params[:email], :password => params[:password])
    if user.save
      render :json => { :auth_token => user.authentication_token }, :status => 200
    else
      render :json => {}, :status => 400
    end

   else
     render :json => { :message => "email or password is not correct" }, :status => 401
   end

end
b. config/routes.rb 新增

post "/signup" => "auth#signup"
註:1. email格式需在前端認證
   2. 密碼也可以在前端請使用者輸入兩次



2. Facebook app_id & secret 隱藏

註冊facebook 開發者之後 會得到 app_id & secret 這資料是需要被保護的

所以這檔案在每次 git 時不會被其他人看到

a. 先將資料移開,新增 config/facebook.yml

development:
  facebook:
    app_id: #請輸入你的
    secret: #我絕對不會給你的
b. 修改 config/initializers/devise.rb內的資料
  
fb_config = Rails.application.config_for(:facebook)
  config.omniauth :facebook, fb_config["facebook"]["app_id"], fb_config["facebook"]["secret"], :scope => 'public_profile,email', :info_fields => 'email,name'
c. 在 .gitignore 其中 # Ignore all logfiles and tempfiles.底下新增

/config/facebook.yml


3. Facebook 手機註冊&登入


使用者登入流程:

1. 使用者點選 facebook登入 => (這時候會連去facebook 請使用者確認)

2. 使用者點選確認 => facebook 回傳 access_token給使用者, 使用者傳給server

3. 此時我們有了 該user的 access_token 再去跟facebook 的 Graph API要資料

4.facebook 回傳資料 server 進行比對 1. 有 fb_id =>登入
                                                                      2. 有 email=>登入
                                                                      3. 什麼都沒有=> 創造新使用者



後台主要在寫後面這兩項

可以找之前的code 會發現 omniauth 在 model/user.rb 之中已經有做了第4步.

所以這邊主要是會來寫 第3步 


--------------這邊是講概念, 實作可跳過--------------

先來講解 Graph API 是什麼

在 omniauth 在 model/user.rb  有用 access_token 跟 Graph API 


 res = RestClient.get "https://graph.facebook.com/v2.4/me",  { :params => { :access_token => access_token } }
版本是 v2.4 

拿access_token 到 Graph API 測試工具 裡面玩 可以看到



about/birthday 是無法取得(因為我沒有設定公開)

我點選右邊 Get Token 設定 點選 user_birthday 



畫面會跳出以下


此時就會有了 birthday



從這邊我們可以知道每個access_token 會因為要要求的內容不同有不一樣的結果


--------------以上是講概念, 實作可跳過--------------


所以這時候我們會取得 access_token 然後跟 Graph API要資料

首先我們要跟他說 我們要哪些資料

在 app/model/user.rb 之中

 res = RestClient.get "https://graph.facebook.com/v2.4/me", { :params => { :access_token => access_token } }

這邊沒辦法帶值回來, 所以要改成以下:

res = RestClient.get "https://graph.facebook.com/v2.4/me",  { :params => { :fields => "email,name", :access_token => access_token } }

接下來的方法要判讀回傳的資料 然後動作 類似 login 那段 params[:access_token]

所以我們會在   /app/controllers/api_v1/auth_controller.rb 新增
 <這邊沒有遵照 don't repeat yourself >



def signup
  success = false
  #POST /api/v1/signup

  if params[:email] && params[:password]

    user = User.new(:email => params[:email], :password => params[:password])
    if user.save
      render :json => { :auth_token => user.authentication_token }, :status => 200
    else
      render :json => {}, :status => 400
    end

   elsif params[:access_token]
       fb_data = User.get_fb_data( params[:access_token] )
         if fb_data
           auth_hash = OmniAuth::AuthHash.new({
             uid: fb_data["id"],
             info: {
               email: fb_data["email"]
             },
             credentials: {
               token: params[:access_token]
             }
           })
           user = User.from_omniauth(auth_hash)
         end
       success = fb_data && user.persisted?
     end

    if success
     render :json => { :auth_token => user.authentication_token,
                       :user_id => user.id}, :status => 200
    else
     render :json => { :message => "email or password is not correct" }, :status => 401
    end

end
但因為會使用到 "rest-client" 所以請確認是否有安裝

在 gemfile 新增 gem "rest-client"

bundle 後 server 重開


-----後記-----


用 Devise + omiauth - facebook 做 網頁的登入

所使用的資料是透過 omiauth 整理後 回傳到資料庫裡面

手機 API 方式   使用RestClient Get 取得.


好文必看!


Graph API是什麼東東?

Graph API 官方文件




Read More
      edit

2016年4月17日 星期日

Published 中午12:28 by with 3 comments

Rails User 建立-1 (Devise + Omniauth-facebook + facebook api) - 我在ALPHACamp 56天

今天在做專案中, 我負責使用者的部分

我會用到 Devise + Omniauth-facebook  + facebook api

好不容易才搞懂... 趕快做個筆記

Devise 的部分可以參考 iHower 實戰聖經 - 使用者認證 

為了版面的完整度... 我還是貼code一下好了


- Devise -


1. 在 Gemfile 新增:


 gem 'devise'
2. bundle install

3. rails g devise:install產生devise設定檔

4. config/environments/development.rb 和 production.rb 加入寄信時預設的網站網址: 

config.action_mailer.default_url_options = { :host => 'localhost:3000' }
5. 確認 app/views/layouts/application.html.erb layout 中可以顯示 flash 訊息

 <p class="notice"><%= notice %></p>
  <p class="alert"><%= alert %></p>
6.確認 routes.rb 中有設定網站首頁位置

 root :to => "welcome#index"
7.輸入rails g devise user產生 User model 及 Migration

8.輸入rails generate devise:views產生樣板

9. 輸入bin/rake db:migrate建立資料表

10. 在需要登入的 controller 加上before_action :authenticate_user!

before_action :authenticate_user!, :except => [:index]
註:index 頁面不需要權限就可以瀏覽, 要在後方補上 :except => [:index] 

11. 在Layout 中加上 登入 / 登出選單

    <% if current_user %>
          <%= link_to('登出', destroy_user_session_path, :method => :delete) %> |
          <%= link_to('修改密碼', edit_registration_path(:user)) %>
      <% else %>
          <%= link_to('註冊', new_registration_path(:user)) %> |
          <%= link_to('登入', new_session_path(:user)) %>
      <% end %>

以上內容出自於 iHower 實戰聖經 - 使用者認證  若有不懂請入內參考!


- Omniauth -


Omniauth 是一套使用者認證系統, 針對不同網站的使用者有不統的gem可以使用, 可以透過該平台使用者帳號登入, 使用者與站方, 也不用擔心儲存密碼的安全性問題

首先要先到 developers.facebook 取得 facebook 的 APP_ID + APP_SECRET

1. 點選右上角, 新增應用程式



2. 選擇網頁



3. 新增名稱




 4. 輸入資料

5. 我把以下的code 貼到  app/views/layouts/application.html.erb 


7.  開發用的 Site URL 請填 http://localhost:3000

8. 取得  APP_ID + APP_SECRET 




接下來要使用的是  omniauth-facebook gem <=內有詳細步驟

我這邊整理一下我的做法:

1. 在 Gemfile 新增:


 gem 'omniauth-facebook'
2. bundle

3. 新增 migration : rails g migration AddOmniauthToUsers

 class AddOmniauthToUsers < ActiveRecord::Migration 
     def change
          add_column :users, :fb_uid, :string 
          add_column :users, :fb_token, :string 

          add_index :users, :fb_uid 
      end 
end
4. rake db:migrate

5. 在config/initializers/devise.rb 底下

config.omniauth :facebook, "輸入剛剛得到的APP_ID", "輸入剛剛得到的APP_SECRET", :scope => 'public_profile,email', :info_fields => 'email,name'
6. 編輯 app/models/user.rb,加上:omniauthable, :omniauth_providers => [:facebook]如下:


devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :trackable, :validatable,
       :omniauthable, :omniauth_providers => [:facebook]
7. 編輯 config/routes.rb

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
8. 編輯 app/views/layout/application.html.erb,加上 Facebook 登入的超連結:

<% if current_user %>
  <%= link_to('登出', destroy_user_session_path, :method => :delete) %>
  ....
<% else %>
    ....
    <%= link_to "登入 Facebook", user_omniauth_authorize_path(:facebook) %>
<% end %>
9. 新增 app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end

end

10.  在 app/models/user.rb,新增一個類別方法self.from_omniauth(auth)

  def self.from_omniauth(auth)
     # Case 1: Find existing user by facebook uid
     user = User.find_by_fb_uid( auth.uid )
     if user
        user.fb_token = auth.credentials.token
        #user.fb_raw_data = auth
        user.save!
       return user
     end

     # Case 2: Find existing user by email
     existing_user = User.find_by_email( auth.info.email )
     if existing_user
       existing_user.fb_uid = auth.uid
       existing_user.fb_token = auth.credentials.token
       #existing_user.fb_raw_data = auth
       existing_user.save!
       return existing_user
     end

     # Case 3: Create new password
     user = User.new
     user.fb_uid = auth.uid
     user.fb_token = auth.credentials.token
     user.email = auth.info.email
     user.password = Devise.friendly_token[0,20]
     #user.fb_raw_data = auth
     user.save!
     return user
   end


- Facebook API -

OK~ 如果貼得順利 , 目前你已經可以用FB 登入你的web

接下來才會是今天的重點 facebook api !

貼code先提到觀念

API 也是採用 MVC概念

Model:
           部分主要是儲存我們要傳送的資料 

View:
        在API中的view 不會真的被看到, 我們會透過 xxx.json.jbuilder ,填寫要傳送的資料, 
可以想像一下, 當手機按下那個按鍵時, 其實是發了一個request 給後端, 後端傳json檔案格式給前端, 裡面資料就包含該 action內的資料.



Controller:
                會把對應的controller 寫在 api/v1底下.


再來講使用者這部分的觀念


a.一開始,使用者註冊, 會得到一組access_token, 之後這組 access_token 就存放在APP內
    (可以說用 email+password 去換一組 token, 後台認可的token)

b.之後APP連接後台時, 就會拿這組 access_token 來確認使用者

c. 登出, 並不會刪除access_token 而是在後台把這組email+password 一組新的access_token, 此時手機上的access_token 不等於後台的access_token, 所以就登出了

實作:

1. 新增 app/models/user.rb 

 before_create :generate_authentication_token

   def generate_authentication_token
     self.authentication_token = Devise.friendly_token
   end
2. rails g migration add_token_to_users.rb

 class AddTokenToUsers < ActiveRecord::Migration

   def change
     add_column :users, :authentication_token, :string
     add_index :users, :authentication_token, :unique => true
 
     User.find_each do |u|
       puts "generate user #{u.id} token"
       u.generate_authentication_token
       u.save!

     end
   end
 end
3. 執行 rake db:migrate

4. 修改 app/controllers/api_controller.rb 

 class ApiController < ActionController::Base
  
   before_action :authenticate_user_from_token!
  
     def authenticate_user_from_token!
 
     if params[:auth_token].present?
       user = User.find_by_authentication_token( params[:auth_token] )
 
       sign_in(user, store: false) if user

     end
   end
  
  end
5. 新增 app/controllers/api_v1/auth_controller.rb



class ApiV1::AuthController < ApiController
 
   before_action :authenticate_user!, :only => [:logout]
 
   def login
     user = User.find_by_email( params[:email] )
 
     if user && user.valid_password?( params[:password] )
       render :json => { :user_id => user.id,
                         :auth_token => user.authentication_token }
     else
       render :json => { :message => "email or password is not correct" }, :status => 401
     end
 
   end
 
   def logout
     user = current_user
 
     user.generate_authentication_token
     user.save!
 
     render :json => { :message => "ok" }
   end
 
 end
6. 在 config/routes.rb 的 scope :path => '/api/v1/', :module => "api_v1", :as => 'v1', :defaults => { :format => :json } do 下方新增 



post "/login" => "auth#login"
post "/logout" => "auth#logout"
7. 修改在 app/controllers/api_v1/auth_controller.rb 中的 def login 把 user = User.find_by_email( params[:email] ) 替換成 



    success = false
 
     if params[:email] && params[:password]
       user = User.find_by_email( params[:email] )
       success = user && user.valid_password?( params[:password] )
     elsif params[:access_token]
       fb_data = User.get_fb_data( params[:access_token] )
       if fb_data
         auth_hash = OmniAuth::AuthHash.new({
           uid: fb_data["id"],
           info: {
             email: fb_data["email"]
           },
           credentials: {
             token: params[:access_token]
           }
         })
         user = User.from_omniauth(auth_hash)
       end
       success = fb_data && user.persisted?
     end 
      
     user = User.find_by_email( params[:email] )
下方 


    if user && user.valid_password?( params[:password] )
      render :json => { :user_id => user.id,
                        :auth_token => user.authentication_token }
替換成:


    if success
      render :json => { :auth_token => user.authentication_token,
                        :user_id => user.id}
8. 最後在  app/models/user.rb 新增 (若原本有請修改成以下)

  def self.get_fb_data(access_token)
    res = RestClient.get "https://graph.facebook.com/v2.4/me",  { :params => { :access_token => access_token } }
 
     if res.code == 200
       JSON.parse( res.to_str )
     else
       Rails.logger.warn(res.body)
       nil
     end  
 end
詳細code 參考  ihower github (以下)




最後在View資料夾中 寫我們要回傳得數值 (使用 jbuilder 格式)


-Postman-


關於測試我們可以使用 postman  <=Chorme 應用程式

1. 測試登入 =>有得到 auth_token



2. 測試 logout =>得到回覆 ok
Read More
      edit