Alex Liang

[Javascript筆記] Hoisting

在Javascript中對於宣告(declaration)會移到作用域的最上方,此預設行為稱為Hoisting。

以下的範例會印出10

1
2
3
x = 10;
var x;
console.log(x);

實際上javascript interpreter會將x的宣告移到上方,也就是:

1
2
3
var x = undefined;
x = 10;
console.log(x);

hositing也會影響function expression的執行,例如:

1
2
3
4
5
6
7
8
9
10
11
function hoistingTest() {
foo(); // 錯誤
bar();
var foo = function () {
alert("foo");
};

function bar() {
alert("bar");
}
}

這段程式碼對javascript來說是長這樣:

1
2
3
4
5
6
7
8
function hoistingTest() {
var foo = undefined;
foo(); // 此時foo為一undefined的變數
foo = function () {
alert("foo");
}
// ...略
}

Javascript雖然語法上是c-like,但在作用域(scope)的觀念有差別,這也會影響程式執行結果。

參考資料:
Javascript Scoping and Hoisting
Hoisting基本解說

[Javascript筆記] Anonymous Function

對一位C/C++ programmer來說,javascript的anonymous function(匿名者函式)是容易讓人困惑的存在。
如何使用沒有identifier的function? 有什麼好處? 在這裡做個筆記。

javascript提供3種宣告function的作法

Function Declarations

一般function的作法,需要提供function name,範例如下

1
2
3
4
5
function multiply(a, b) {
return a * b;
}

console.log(multiply(3, 4)); // Print 3 * 4

The Function() Constructor

類似C++的建構者函式 (constructor),只不過是用在function上

1
2
var mulitplyFunc = new Function("a", "b", "return a * b");
var x = mulitplyFunc(3, 4);

一般來說不建議用此方式宣告函式

Function Expressions

也就是這篇的主角,function expression不需要function name,可視為variable

1
2
var mulitplyFunc = function (a, b) { return a * b; };
var x = multiplyFunc(3, 4); // Calculate 3 * 4

使用anonymous function的好處

  1. 可用來實做Closure,實現design pattern的工廠方法
  2. 簡化程式碼,提高易讀性
    之前要用C++實作工廠方法時,需要dynamic binding的技術,確實要花點心思
    下一篇討論closure

參考來源:
Javascript function基本教學
關於lambda觀念的說明
比較ruby和js的anonymous function
Javascript function declarations vs function operators

[Rails] 使用figaro管理密鑰

figaro是一個管理機密資訊或密碼的gem,以下介紹如何同步資訊到heroku上

安裝figaro

Gemfile
1
gem "figaro"
1
$ bundle install
1
$ figaro install

管理機密資訊

假如有一組key不希望公開至github,則我們先把資訊存在yml檔,再使用ENV存取

config/application.yml
1
2
3
product_app_id: "2924"
product_key: "7ad1a978f7dd7f9a1117"
product_secret: "11dcb896a0ffb85d373"

在initializer中存取資訊
config/initializers/pusher.rb
1
2
3
Product.app_id = ENV["product_app_id"]
Product.key = ENV["product_key"]
Product.secret = ENV["product_secret"]

佈署至HEROKU

1
$ figaro heroku:set -e production

查循目前設定

1
$ heroku:config

參考來源:
figaro github

[Rails] Resolution Tracker-User Story

上一篇解釋這個專案的想法從何而來。這一篇開始寫user story。

Version 1.

1. 身為使用者,我能夠以email登入網站
2. 身為使用者,我能夠新增目標和完成時間
3. 身為使用者,我能夠刪除目標
4. 身為使用者,我能夠透過email分享目標給朋友
5. 身為使用者,我能夠設定通知信寄送日期
6. 身為使用者,我能夠看到目標的進度

Version 2. update January 14,2016

1. 身為使用者,我能夠以email登入網站 
2. 身為使用者,我能夠新增目標和完成時間
3. 身為使用者,我能夠刪除目標
4. 身為使用者,我能夠勾選己完成的目標
5. 身為使用者,我能夠透過email分享目標給朋友 
         * 身為使用者,我需要登入才能看見朋友的目標
   * 身為使用者,我能夠設定要分享權限
    6. 身為使用者,我能夠設定通知信寄送日期
7. 身為使用者,我能夠看到目標的進度
     * 進度會以百分比顯示    
    8. 身為管理者,我能管理一般使用者的帳號
     * 身為管理者,我能停權一般使用者的帳號
   * 身為管理者,我能恢復一般使用者的帳號

[Rails] Resolution Tracker-KICK OFF!

前天上完目標設定,對接下來一年有更具體的規劃

在短期目標中,我寫下要轉職為rails developer。

要說服別人,當然得拿出作品來。於是resolution-tracker的想法就產生了⋯⋯

那天活動結束,老師要我們找3~4人的小組,大家互相督促。 但從過去的經驗來看,這樣還是不夠的

所以我才想要用rails打造一個小組追蹤目標進度的網站,把目標和時程放上去,接近設定的時間時會自動寄信提醒。

這個作品就用xdite的專案管理技巧來實作吧(真是一魚三吃 XD)

首先是規劃時程。我己經昭告組員會在過年時放出beta版,以星期來看:

1. 1/4~1/10   寫user story,開始實作
2. 1/11~1/17  實作
3. 1/18~1/24  release preview version
4. 1/25~1/31  修改樣式和bug 
5. 2/1~2/7        release beta version

對我來說,這schedule達成率是60%左右,但我有信心能完成它! 

2016/1/17
激情過後,今天在家實作。發現在view的部分還是不太熟,要做出腦中的畫面還是需要看之前的作業。
而且最重要的寄信提醒功能還沒做,要加快腳步了。

[Rails] 使用carrierwave實作圖片上傳

上一篇說明如何設定AWS S3。這一篇則是記錄使用carrierwave實作圖片上傳。

本例我們將建立一個model:Photo 配合carrierwave實現圖片上傳

安裝gem carrierwave

Gemfile
1
2
gem "carrierwave"
gem "mini_megick"
1
2
>>bundle install
>>rails g uploader image

會產生uploaders/image_uploader.rb

設定autoload_paths

config/application.rb
1
2
3
4
5
6
module Artstore
class Application < Rails::Application
...(略)
config.autoload_paths += %W(#{config.root}/app/uploaders)
end
end

建立model:Photo

1
2
>>rails g model photo product_id:integer image:string
>>rake db:migrate

假如己有一個product model,設定product和photo的關聯

models/photo.rb
1
2
3
4
5
class Photo < ActiveRecord::Base
belongs_to :product

mount_uploader :image, ImageUplader
end
models/product.rb
1
2
3
4
5
class Product < ActiveRecord::Base
has_one :photo

accepts_nested_attributes_for :photo
end

新增product時能新增圖片

app/controllers/admin/products_controller.rb
1
2
3
4
def new
@product = Prodcut.new
@photo = @product.build_photo
end

將upload資料夾加入gitignore

.gitignore
1
public/uploads

以上是使用carrierwave上傳圖片的流程,下一篇說明使用figaro管理s3密鑰。

[AWS] 使用S3存放上傳圖片

假如網站部署到heroku,通常需要另外的空間存放圖片及檔案。這裡記錄AWS S3的設定。

首先,登入AWS後台,選擇帳號設定
螢幕快照 2015-12-24 下午11.09.20.png

選擇“Get Started with IAM Users”
螢幕快照 2015-12-25 下午10.26.55.png

新增user,輸入名稱後,要勾選Generate an access key for each user
螢幕快照 2015-12-27 下午9.24.07.png

完成後可下載Access Key。Access Key ID和Secret Access Key之後會用到
螢幕快照 2015-12-27 下午9.28.25.png

回到User頁面,點選剛才建立的user
螢幕快照 2015-12-27 下午9.39.12.png

點選”Attach Policy”
螢幕快照 2015-12-27 下午9.42.00.png

在policy type填s3,選擇出現的項目,再點Attach Policy
螢幕快照 2015-12-27 下午9.45.04.png

完成權限設定
螢幕快照 2015-12-27 下午9.47.04.png

接著回到後台主畫面,點選S3
螢幕快照 2015-12-27 下午9.01.50.png

進入S3後台,新增bucket,Region選擇Northern California
螢幕快照 2015-12-27 下午9.05.26.png

以上是S3的設定,下一篇介紹如何透過gem將網站的圖片上傳到S3。

[Rails] MVC設定基本流程

rails是使用MVC架構的framework。學習一段時間後,更能體會這種架構開發web application帶來的方便。

所謂的MVC,指的是Model(資料操作)、View(前端效果)和Controller(流程控制)。

剛開始接觸時,對MVC的控制會感到一頭霧水,這裡以rails 101為範本做簡單的流程介紹:

  1. 設定routing,讓http request到對應的controller action執行

    config/routes.rb
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Rails.application.routes.draw do
    root "groups#index"
    resources :groups
    end
    ```

    2. 在controller新增action,例如討論版的首頁就需要建立index action
    ``` ruby app/controllers/groups_controller.rb
    class GroupsController < ApplicationController
    def index
    @group = Group.all
    end
    ...
    end
  2. 設定model,思考需要哪些資料欄位以及和其它資料表的關係。例如group和post有has_many的關係

    app/models/group.rb
    1
    2
    3
    4
    5
     class Group < ActiveRecord::Base
    validates :title, presence: true #表示title這個欄位必填
    has_many :posts, dependent: :delete #當group被刪除時,底下的post也得刪除
    ...
    end
  3. 設定view。如果需要使用URL helper,得思考request要發到哪個action,例如:
    ruby app/views/groups/index.html.erb <div class="col-md-12"> <div class="group"> <%= link_to("New group", new_group_path, class: "btn btn-primary pull-right") %> </div> ...
    使用者點擊”New group”這個按鈕時,會發一個request至new這個action並將頁面轉到/groups/new.html

以上是簡單的流程。這四個步驟會依功能需要增加複雜度,開始實作前也得思考model間的關係。