- Feb 28 Tue 2012 16:34
在Ubuntu 11.10 64-bit底下更新Chrome flash pulgin
- Jun 03 Fri 2011 16:58
Ruby on Rails學習筆記 - 依照solr的比對分數作排序
(前略,因為不知道要寫什麼引言XD)
這陣子一個很苦惱我的問題,
就是在solr傳出來的結果是依照關聯性(score)排序,但下了query後,卻變成用primary key排序。
因為Ruby語法還不熟,加上不知道用什麼關鍵字去Google,整個卡關卡超大,
總之,是備忘用筆記。
原則上,最初的一步是在solr的fl參數,將score加上去,像是 :fl => "score, id"這樣,
才會把比對的分數一併傳出來
問題來了,在query時要用solr的id去作,同時用score的分數作排序
後來才知道應該要傳hash進去,以下則是邏輯上的思考
(由於id是primary key,因為不會重複,所以作為hash的key)
(而不同的id可能會有相同的score,所以score作為hash的value,拿score當key會天下大亂XD)
# res is the result of solr
key_array = res.map { |k| k['id'] }
value_array = res.map { |v| v['score'] }
id_and_score_array = [key_array, value_array].transpose
id_and_score_hash = Hash[*id_and_score_array.flatten]
這樣target_hash就是我要的hash了
最後是query時要用到sort來根據score作排序,但拉資料要用id來拉
post_find = Post.find(key_array)
post_score_array = [post_find, value_array].transpose
post_score_array.sort! { |a,b| b[1] <=> a[1] } # sort by value
@post = Hash[*post_score_array.flatten].keys
這樣@post就是依照solr的score去排序了,但以上顯然是很不漂亮的寫法XD
所以改成以下寫法,就可以得到排序後的結果了
id_score_hash = Hash[*res.map { |h| [h['id'], h['score']] }.flatten]
@post = Post.find(id_score_hash.keys).sort {|a, b| id_score_hash["#{b.id}"] <=> id_score_hash["#{a.id}"]}
- May 17 Tue 2011 12:48
Ruby on Rails學習筆記
前略(誤)
總之開始在新環境後,接著就是學習Ruby on Rails
排版不是很好看,還請見諒
學習流程如下:
- Getting Started with Rails
中文化
(1.5 手刻Getting Started with Rails) - XDite的2010 Ruby on Rails 書單 與 練習作業
還有ihower的作業: 簡易論壇系統
相當建議新手照著Getting Started with Rails先全作一遍
用Scaffolding去作也沒關係,先熟悉一次流程,大致了解一下整體運作
(若本來就有相關經驗的話可以跳過Scaffolding這段,直接手刻)
參考資料如下:
- Ruby on Rails 實戰聖經
- Rails API Documentation
- Try Ruby!
- Google大神XDDD (這其實用最多)
那麼開始筆記,分享一些整體遇到的重點、問題與解決方案
事前準備,好的機器與好朋友(無誤),前者方便你使用,後者亦同(喂喂)
好的版本控制跟上手的編輯器,可以幫助不少,建議是git作版本控制,因為很多資源可以撈阿XD
看一下網站上的前兩章了解一下基本概念
=以下都在ubuntu 10.04底下,使用Ruby 1.8.7與Rails 3.0.7完成,沒用RVM=
用中括號的數字,表示是Getting Started with Rails內的章節,像是[7.3]就是該網頁上的7.3的部份
- 0. 在朋友的協助下,設定好git, vim, rails, mysql, phpmyadmin的環境(以後重灌再來作筆記)
- 1. ([3.1] ~ [4.3]) 從Getting Started with Rails開始學習
1.1 rails new [你的專案] -d mysql (要用到MySQL的話就照這樣作,其他的就不清楚了)
-d指定要用的database,預設是SQLite3,在new的時候先指定,避開找不到東西的問題
設定好後,就踩到雷了XD,因為下兩步是作bundle install跟 rake db:create,
為了避開mysql gem版本的問題,編輯[你的專案]底下的Gemfile,新增gem 'mysql2', '~>0.2.7'
1.2 bundle install,然後等他跑完後再下rails db:create
1.3 rails server -p [指定的port],預設是3000
開瀏覽器看看http://localhost:3000,沒問題的話就會有歡迎畫面
需要Hello world的話一樣照著流程作,這部份應該沒什麼問題,就移除public/index.html就好
- 2. ([5] ~ [6.12]) Scaffolding與MVC架構
2.1 rails generate scaffold Post name:string title:string content:text
會產生15個檔案,各個檔案的功能在網頁上寫得很清楚,特別要注意的是
Model的post.rb,View的.erb檔,還有Controller的posts_controller.rb,及config/routes.rb與Migration檔
這些內容可以方便將來手刻時,供自己練習的範本
(若更改到routes,記得將server按Crtl+C停掉,在重開一次)
2.2 rake db:migrate後,可以照著網頁的作一陣子,先熟悉MVC架構
2.3 rails console不熟Ruby的可以先放著console mode不管
2.4 在posts_controller.rb的index, show, new, edit,Scaffolding都貼心的幫你做好相對應的View了
在Getting Started網頁的6.5提到validate,可以驗證資料是否存在,還有使用限制
而6.9則提到render 'form',把這想成程式碼讀到這行時,
會跑到同一資料夾底下的_form.html.erb(檔案格式是固定的),直到該檔案的程式碼跑完再回來
(render也可以傳參數進去,不過暫時還沒用到)
- 3. ([7.1] ~ [10]) 加留言的MVC與路徑
3.1 rails generate model Comment commenter:string body:text post:references
然後rake db:migrate後,Post跟Comment就有從屬關係
(Model的comment.rb有belongs_to,而post.rb則有has_many)
3.2 照著[7.3]修改config/routes.rb,可以產生巢狀路徑,可以下rake routes來了解現在該檔案定義了哪些路徑
任何_path字尾的字,理當說都要在定義的路徑中出現 (像post_path就是對應到post的GET/PUT/DELETE)
然後rails generate controller Comments產生controller
3.3 [7.4]有redirect_to post_path(@post),這邊的(@post)表示將@post作為參數,傳到路徑/post/:id中
若之後路徑有兩三個需要傳入參數的話,則用逗號分開
3.4 [8.1] ~ [8.2]練習簡單的重構,以及render的用法
[9.1]了解:dependent的使用
[10]簡易的認證,以後可能會用到其他的plugin或gem來作認證,這邊大概了解一下before_filter的用法
- 4. ([11] ~ [12]) 開始覺得這網站的guides有點煩悶......XD
這邊不好吸收倒是真的,不過一樣先照著完成 (helper的觀念還在混淆中)
有時間的話,不妨開新project,手刻Scaffolding的部份,再加強與熟悉一次CRUD基本的概念
特別是第一次手刻不用急著一次做完CRUD,一個個作更容易了解整體流程 (當時感覺像是發現新大陸...XD)
也可以試著將Post加一個非公開文章的boolean,然後練習用scope + lambda來顯示所有公開或隱密的文章
(比方說用Post.is_publiced(true)表示所有公開文章,用Post.is_publiced(false)表示所有隱密文章)
- 5. 實戰作業:簡易論壇系統 - Forum 與 Post 兩個 model
用http://forum.local/forums/1/posts/2來表示文章網址,兩層的resources再加強一次巢狀路徑的概念
總之,先把Forum生出來,做好CRUD,把第一層做出來,原則上照著Getting started網站依樣畫葫蘆就好
5.1 實做Post,別忘了belongs_to跟has_many,還有routes.rb檔的修改(改完用rake routes看有無錯誤),
Post的controller跟view會有很多地方要注意XD(假設你跟我一樣是想copy Forum得來用的話XD)
由於處理Post時,要先給定forum_id才會知道文章是在哪一個forum底下,
在有forum_字眼的path,都要傳參數進去 (像forum_post_path(@forum, @post)這樣一次傳兩個參數)
然而因為會在各個action都用到類似的語法,善用before_filter
5.2 確認各層網址有無作用,就是/forums, /forums/1, /forum/1/posts, /forum/1/posts/2各自要看到正確的東西
會比較傷腦筋的是/forums/1這層的view要手刻還是另外用render都可以
post的edit與new的view可能會有路徑問題,
用<%= render 'form', { :url => forum_post_path(@forum, @post) }%>傳參數進去form
- 6. 實戰作業 - 使用者與權限
在沒另外裝過plugin跟gem的經驗下,這邊卡關會卡很大
(restful-authentication的plugin與devise gem請擇一,以下是我用前者的經驗)
6.1 rails plugin install git://github.com/Satish/restful-authentication.git
完成後,到vendor/plugin/下把該資料夾改名成restful_authentication
再將config/application.rb的Application新增一行 config.autoload_paths << "#{Rails.root}/lib"
(避免找不到檔案)
最後把user的view加到需要顯示的地方
6.2 文章權限,在建Post時沒有考慮到user_id的話,這時候就乖乖的把這個integer加上去...
利用before_filter檢查使用者,以及if !(current_user && @post.user_id == current_user.id)來判斷
而新增文章時,則記得在create底下把user_id指定進去
- 7. 實戰作業 - 分頁與counter_cache (kaminari gem或will_paginate plugin擇一)
7.1 在Gemfile內加一行gem 'kaminari'後下指令bundle,
或rails plugin install git://github.com/mislav/will_paginate安裝
原則上這邊照著github上的說明應該不會卡什麼關
7.2 Post的Model,在belongs_to後面加上:counter_cache => true,
然後在Forum新增posts_count的column(記得給預設值0)
(其實這邊有點忘了當初是怎麼做的,之後有重作或遇到一樣問題,再補上詳細流程)
- 8. 實戰作業 - 文章排序
在Model裡面使用scope(舊版Rails叫named_scope),然後整個卡超大XD,怕自己忘記,下面直接給我的作法
8.1 在Post model加入scope :ordered, lambda { |user_order| { :order => (user_order || 'id') } } (預設用id排列)
8.2 在Forum controller的show加入sort_params = { "by_user" => "user_id", "by_date" => "created_at DESC",
"by_id" => "id", "by_update" => "updated_at" }
然後把@posts等號後面改成@forum.posts.ordered(sort_params[params[:sort]])
(有用到分頁的部份記得要再另外補上去)
8.3 在view裡面,用來排序的link_to後面加上:sort => "by_id" (或是by_date/by_id/by_update依不同方式排列)
- 9. 實戰作業 - 用paperclip gem上傳檔案
原則上參考paperclip github,基本上是無痛解決,重點是:html => { :multipart => true }
(若有用github的話,建議在.gitignore內加入public/system/avatars/)
- 10. 實戰作業 - Admin與管理後台
在User的table新增一個boolean的column,判斷是否為admin,然後用attr_accessible 或 attr_protected保護
當初一直在苦惱要怎麼指定true或false,直到有用的朋友跟我說:「手動指定就好啦。」才覺得自己很蠢XD
10.1 管理後台,簡單說就是給管理者專用的,所以理當要有自己獨有的controller跟view,還有自己用的路徑
先從routes.rb,新增一個admin的namespace
(要獨立一個resources或是照原架構放兩層都可以,看admin用的controller跟view)
10.2 把controller跟view獨立出來作業,路徑都指定好,最後再用before_filter擋掉非admin權限的使用者
(造原架構複製貼上放兩層的話,controller要改成class Admin::PostsController < ApplicationController)
- 11. 實戰作業 - 產生假資料
直接參考範例,/lib/tasks/底下新增my_task.rake,重點在=> :environment,下rake -T會多dev:testPrint跟fake
namespace :dev do
desc " -Just test- "
task( :testPrint ) do
puts "kerokero"
end
desc " Fake post "
task( :fake => :environment ) do
@forum = Forum.find(3)
@post = @forum.posts.new
@post.title = "From task"
@post.content = "Fake date"
@post.user_id = 3
@post.save
puts "Make fake post complete."
end
end
以上大概花了兩個多禮拜才算做完,事實上最一開始在學git還挺吃力的,因為那是一種習慣與概念的建立
相較之下在練習getting start時,單純的操作工具做事就快很多了(不過很是很容易卡住,有用的朋友在這種時候就非常之重要)
然而用了git,養成經常commit的習慣,做錯的話可以一下子修正回來
=小撇步=
model裡面,可以用before_validation來設定預設值
用annotate gem,然後下bundle exec annotate,可以在一些檔案底下,把對應的Schema information記進去
其他有想到再補上來
- Apr 22 Fri 2011 01:07
Det的好人回憶錄
那麼,作為第一篇網誌,就聊聊Det這好人的一些瑣事吧(笑)
我猜不少人會認為說,一個待退的員工,在工作上的事情理當不需如此操心。
事實上,在其他同仁的評價中,將離職的員工是該如此。
但若是沒有其他人可以代替你的職務,或許你會跟我一樣,帶著些微而又不必要的責任感。
是的,小弟我就是有著這種窘境,
雖然我已經被公司放生很長一段時間了,其實搞不好上頭也不清楚我平常再做些什麼。
實際上上頭覺得怎樣並不重要,問題在同僚與客戶上,有著許多你會想努力去解決,但又無能為力的情況。
而你只希望,同僚可以好過一些,至少不會被客戶追著打,但最後還是無能為力。
做設備的,似乎不該像軟體業一樣,在機器還沒ready前就出貨,苦的是無盡維護的人員與實做跟修改的程序師。
(軟體業一般來說,會先推出後再加以patch,不太可能等到軟體完全成熟後再推出)
可以想像,未被發現的設備機構限制,得由軟體去避開(而且你還不知道哪裡有問題,通常是採到地雷後才知道),
然後設計部的只會說這是硬體限制(而且是他們尚未得知的),主管只會要你把大便吃下來,跟人體蜈蚣一樣。
問體在此,原本嶄新的機構便是為了加速流程,
但礙於硬體限制,軟體為了避開,而迫使加大流程時間,這樣硬體的優勢立刻蕩然無存。
那個,可以想像有三種解決的方案:
1. 客戶認賠,皆大歡喜
2. 公司認賠,機台回收重做
3. 軟工認賠,程式砍掉重練
顯然的真相永遠只有一個。
工作上的好人,就先點到這邊,反正對於待退員工來說,這些都只是牢騷。