目前分類:Rails筆記 (13)

瀏覽方式: 標題列表 簡短摘要

這個功能其實從 Rails 2 就有了(也許更早,我不太確定),不過我最近才有機會研究了一番,看的也是 Rails 3 的文件。

要在 model 裡面使用 serialize 有一個限制,就是該欄位必須是 text 格式,所以在玩這個功能之前請先 migrate 一個 text format 的 column 出來。

寫法如下:

class User < ActiveRecord::Base
  serialize :preferences
end

serialize 第一個參數是欄位名稱,第二個是 class 。可以有變化的地方在 class 這個參數,如果不給預設就是使用 YAML ,可以給 Array, Hash 甚至是自定的 class ,看你存什麼格式就會照著寫入該欄位內。

比方說接續上面的範例:

user = User.create(:preferences => { "background" => "black", "display" => large })
User.find(user.id).preferences # => { "background" => "black", "display" => large }

 

如果 class 不對,比方說格式指定 Hash ,你卻塞給他一個 Array ,那麼就會跳出 SerializationTypeMismatch 錯誤。

class User < ActiveRecord::Base
  serialize :preferences, Hash
end

user = User.create(:preferences => %w( one two three ))
User.find(user.id).preferences    # raises SerializationTypeMismatch

特別注意到,如果你使用一個 class ,那麼它會自動變成你這個 model 的 instance method ,非常的酷!

class User < ActiveRecord::Base
  serialize :preferences, OpenStruct
end

user = User.new
user.preferences.theme_color = "red"

 

最後,由於欄位需要做初始化的動作,可以在 migrate 時就指定預設值 "--- {}" ,但是 MySQL 5.x 會對 text 格式的欄位忽略預設值,因此建議作法是用 after_initialize callback ,去呼叫同名 method ,雖然會對 performance 會造成些微的影響,但可以避免一些錯誤出現。

def preferences 
  read_attribute(:preferences) || write_attribute(:preferences, {}) 
end

 

參考資料:

http://api.rubyonrails.org/classes/ActiveRecord/Base.html
THE RAILS 3 WAY

文章標籤

笨笨小蟹 發表在 痞客邦 留言(1) 人氣()

本篇的作法是我參考了文末的 reference 後融合而成。

在 app/controllers/application_controller.rb ,首先在最前面加上

unless Rails.env == 'development'
  rescue_from Exception, :with => :render_500 
  rescue_from RuntimeError, :with => :render_500
  rescue_from ActiveRecord::RecordNotFound, :with => :render_404
end

然後定義 render_404 、 render_500 、 render_optional_error_file 這三個 method

def render_404
  render_optional_error_file(404)
end

def render_500
  render_optional_error_file(500)
end

def render_optional_error_file(status_code)
  status = status_code.to_s
  if ["404", "422", "500"].include?(status)
    render :template => "/errors/#{status}.html.erb", :status => status, :layout => "errors"
  else
    render :template => "/errors/unknown.html.erb", :status => status, :layout => "errors"
  end
end

打開 config/routes.rb ,寫上所有找不到頁面要處理 404 的 route

match "*other", :to => "welcome#handle404"

在 app/controllers/welcome_controller.rb 加上 handle404 action

def handle404
  render_404
end

最後把 /public/404.html, 422.html, 500.html 刪除,這樣就完成了!

 

Reference:
render_optional_error_file method
rails3定制404和500错误

Extra:
另外我後來還有找到 gem 可以處理 errors 頁面,但因為那時候 code 都寫完了所以沒有測,僅列出文章和連結提供參考
Helder Ribeiro — Dynamic Error Pages in Rails 3 with Goalie
wrangler gem
dynamic_errors gem

文章標籤

笨笨小蟹 發表在 痞客邦 留言(1) 人氣()

假設狀況是要對 users table 的某一筆資料做 validate email 欄位檢查,打開 rails console 後下

user = User.find 1
user.save # => false
user.errors.invalid? :email # => true/false

當然前提是你的 User model 已經有設定好 validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

Rails 3 使用這個 chinese_permalink gem 在 model 內會出現未定義 chinese_permalink method 的情形

解法是自己新增 config/initializers/chinese_permalink.rb 檔案,內容是

ActiveRecord::Base.send :include, ChinesePermalink

以上是我在專案內的寫法,如果你不喜歡新增檔案,那麼直接在 config/environment.rb 內直接加入這行程式,也是可以解決。

 

另外使用 permalink 會有 SEO 分散的問題,所以要記得在頁面的 head tag 內要加上 canonical url 處理

http://blog.othree.net/log/2011/03/03/canonical-url/

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

<%= f.input :brand_id, :collection => @brands, :include_blank => false, :label => "品牌" %>

使用 :collection ,就會自動切換成 select tag ,不用再加 :as => :select 啦。

但是預設會生出一個空白選項,你可以用 :prompt => "預設文字" 設定它,或是像我一樣使用 :include_blank => false 移除這個空白選項。

文章標籤

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

原本我是使用 handicraft_form ,但因為現在 ihower 沒再更新他了,在同行以及 railscast 建議之下改用 simple_form 。

改進的地方令人驚訝,首先你根本就不用管表單內各欄位要用哪種 form tag ,寫的時候一律用 f.input , simple_form 會根據 column type 去對應產生需要的 form tag ,真的要自訂再用 :as => :wanted_tag 去改。詳細可以參考專案內的 Mappings/Inputs available 。

https://github.com/plataformatec/simple_form
https://github.com/techbang/handicraft_helper

如果你對設定上不滿意,可以在 config/initializers/simple_form.rb 進行你需要的設定。
如果需要 i18n ,可以新增config/locales/simple_form.zh-TW.yml ,內容如下,我自己只有制定基本中文化而已:

zh-TW:
  simple_form:
    "yes": '是'
    "no": '否'
    required:
      text: '必填'
      mark: '*'
      # You can uncomment the line below if you need to overwrite the whole required html.
      # When using html, text and mark won't be used.
      # html: '<abbr title="required">*</abbr>'
    error_notification:
      default_message: "很抱歉,請您再檢查一下:"

使用 simple_form 要注意的是,必須餵給他 @object ,而不能用 symbol 。 simple_form 會自動幫你抓出 model 內設定驗證的欄位,自動加上 * 表示必填,並且如果漏填噴 error_messages 時,自動幫你補在欄位後方。

ps. Rails 3 拿掉了 error_messages, error_messages_on, error_messages_for 等 method ,如果想要使用,必須安裝 dynamic_form 。

https://github.com/rails/dynamic_form

文章標籤

笨笨小蟹 發表在 痞客邦 留言(2) 人氣()

1. script/generate scaffold(自己 generate 才會了解流程)

2. elsif,只能用到 if...else...end(原因是寫 elsif 多半會有意圖不明的情況)

3. 在判斷式上下 query (query 會回傳 true)

4. 在 erb 內寫 <% if blah%> <% end %>(這種 code 應該要丟到 helper)

5. 全域變數塞到 environment.rb ,打成 const 來用(多用 const 保持身心健康)

6. 字串不要用+號,改用 "xxx #{blah}" 這種寫法(使用+號時, ruby 會產生新的物件)

7. 變數或 method 名稱不要縮寫,obj 請寫成 object、val 請寫成 value(避免意圖不明)

8. 少用 block ,會有雷(親身慘痛經驗,block call 會根據 erb 呼叫與否決定是否要 return)

9. controller 裡面不要寫 html code,helper 也是,最好用 content_tag 包起來(維持乾淨以及維護方便)

10. 不要在 model 裡面的 method 或 name_scope 內,塞入是 view 所需要但 db 沒有的資訊(MVC架構分層要清楚,每一層都必須吐出該層的 pure data)

11. 如果 plugin 的效果你不滿意的話,不要直接去 hack ,而是利用 ruby 可以 override method 的特性處理。

 

想到再繼續補....

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

create 和 build 這兩個 method ,要先建立好 model 之間的關連,才會自動產生。
直接使用會出現 undefined method 的錯誤。

http://ihower.tw/training/activerecord.html

可以參看設定關連 Relationship 這一段。

http://blog.mrbrdo.net/2009/10/27/ruby-on-rails-new-vs-create-vs-build/

這個網頁清楚的說明,運行這兩個 method 的差別和 console 執行的結果。

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

目標:新機器上裝好 RoR 的 production 環境,並且可以做 deploy ,讓 local 端寫好的專案可以發佈上去並正常瀏覽。

注意:本目標不包含 git server 安裝,可以先利用 github 完成 repository 部分的需求。

參考資料

http://github.com/jnstq/rails-nginx-passenger-ubuntu
http://articles.slicehost.com/2009/4/9/debian-lenny-installing-apache2-and-php5
http://articles.slicehost.com/2009/7/3/debian-lenny-installing-passenger-with-apache
http://articles.slicehost.com/2009/4/9/debian-lenny-ruby-on-rails

 

流程:

1. 裝上 ruby 1.8.7
2. 裝上 rubygem / mongrel / rmagick
3. 裝上 rails 2.3.5
4. 裝上 git
5. 裝上 apache / mysql
6. 裝上 mod_rails
7. 裝上 實驗 project 測試運行
8. 開 deploy 用帳號 "apps"
9. 用 capistrano deploy 實驗 project

 

步驟說明:(註:藍底區塊表示terminal)

開始前請先 Update and upgrade the system

sudo apt-get update  
sudo apt-get upgrade


1. 裝上 ruby 1.8.7

注意這邊的 ruby 是要裝以 c 語言重寫過的 Ruby Enterprise Edition

Check for newer version at http://www.rubyenterpriseedition.com/download.html

Install package required by ruby enterprise, C compiler, Zlib development headers, OpenSSL development headers, GNU Readline development headers

sudo apt-get install build-essential zlib1g-dev libssl-dev libreadline5-dev

Download and install Ruby Enterprise Edition

wget http://rubyforge.org/frs/download.php/66162/ruby-enterprise-X.X.X-ZZZZ.ZZ.tar.gz
tar xvfz ruby-enterprise-X.X.X-ZZZZ.ZZ.tar.gz
rm ruby-enterprise-X.X.X-ZZZZ.ZZ.tar.gz
cd ruby-enterprise-X.X.X-ZZZZ.ZZ/
sudo ./installer


Change target folder to /opt/ruby for easier upgrade later on

Add Ruby Enterprise bin to PATH

echo "export PATH=/opt/ruby/bin:$PATH" >> ~/.profile && . ~/.profile

Verify the ruby installation

ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux], MBARI 0x6770, Ruby Enterprise Edition 20090928

我當時安裝所下的指令如下:

sudo apt-get install build-essential zlib1g-dev libssl-dev libreadline5-dev
wget  http://rubyforge.org/frs/download.php/68719/ruby-enterprise-1.8.7-2010.01.tar.gz
tar -zxvf ruby-enterprise-1.8.7-2010.01.tar.gz
cd ruby-enterprise-1.8.7-2010.01
sudo ./installer

2. 裝上 rubygem / mongrel / rmagick

這一步當初真是把我搞慘了,原因出在超多雷的 rmagick ,讓我硬生生的跳過,直到整個目標都完成才回頭找到底怎麼樣才能裝好 rmagick @@

以下的指令已經修正過,應該是不會有問題.....

wget  http://rubyforge.org/frs/download.php/69365/rubygems-1.3.6.tgz
tar -zxvf rubygems-1.3.6.tgz
sudo ruby setup.rb
alias gem='gem1.8'

sudo /opt/ruby/bin/gem install mongrel

rmagick 的部份,要先用 source code 來裝 ImageMagick,再用 gem 裝 rmagick
千萬不可以用 apt-get 裝 ImageMagick ,裝下去就會爆炸準備重來一次吧........

sudo apt-get install libperl-dev gcc libjpeg62-dev libbz2-dev libtiff4-dev libwmf-dev libz-dev libpng12-dev libx11-dev libxt-dev libxext-dev libxml2-dev libfreetype6-dev liblcms1-dev libexif-dev perl libjasper-dev libltdl3-dev graphviz gs-gpl pkg-config
wget  ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
tar xvfz
ImageMagick.tar.gz
cd
ImageMagick-6.6.0-4/
./configure --with-modules(重要!參數下錯待會兒 gem install rmagick 就會失敗)
make
sudo make install

ps. 附上當初找到的configure參數,如果用--with-modules也裝不起來可以試試。
./configure --disable-static --with-modules --without-perl --with-quantum-depth=8 --with-bzlib=no --with-libiconv

To avoid an error such as:
convert: error while loading shared libraries: libMagickCore.so.2: cannot open shared object file: No such file or directory
sudo ldconfig

sudo /opt/ruby/bin/ruby /opt/ruby/bin/gem install rmagick

 

3. 裝上 rails 2.3.5

sudo /opt/ruby/bin/gem install rails

 

4. 裝上 git

sudo apt-get install git-core

 

5. 裝上 apache / mysql

sudo apt-get install apache2 apache2.2-common apache2-mpm-prefork apache2-utils libexpat1 ssl-cert
sudo apache2ctl graceful

This should be installed before Ruby Enterprise Edition becouse that will install the mysql gem.
sudo apt-get install mysql-server libmysqlclient15-dev
sudo /opt/ruby/bin/gem install mysql
(沒有先安裝 mysql 再安裝 ruby 的話,就要下這行)

 

6. 裝上 mod_rails

sudo /opt/ruby/bin/gem install passenger
sudo apt-get install apache2-prefork-dev
sudo /opt/ruby/bin/passenger-install-apache2-module
sudo vim /etc/apache2/apache2.conf


貼上
LoadModule passenger_module /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.2.11/ext/apache2/mod_passenger.so
PassengerRoot /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.2.11
PassengerRuby /opt/ruby/bin/ruby


sudo /etc/init.d/apache2 restart

 

7. 裝上 實驗 project 測試運行

指令 git clone 拉下 testrails project
設定 database.yml、db migrate
rake dev:buld RAIL_ENV="production"
sudo vim /etc/apache2/apache2.conf
設定 virtual host

<VirtualHost *:80>
ServerName rails.wildjcrt.org
DocumentRoot "/home/
test/projects/testrails/public"
</VirtualHost>


sudo /etc/init.d/apache2 restart

 

8. 開 deploy 用帳號 "apps"

sudo /opt/ruby/bin/gem install capistrano

useradd -g deploytest apps
ssh-keygen rsa

將 id_rsa.pub 貼到github

 

9. 用 capistrano deploy 實驗 project

capify .
編輯 config/deploy.rb 做好設定
cap deploy:setup
cap deploy

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

git add 前,要記得先看一下 git status ,不需要 commit 的就不要加入。

git commit 之前,要確認一下 .gitignore ,以免把 test 或是 database 的資料也丟上去了。

工作平台上的 rails 指令,要記得加上 RAILS_ENV=production 。

太多判斷式的 code ,就丟到 helper 裡面包起來,程式也會比較易讀。

helper 裡面的 method ,一定要寫 return ,避免呼叫後不曉得是哪段程式 return 結果。

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

簡單總結,就是實作一個 blog

1. 開設 Rails 專案,設定好 Post model 的 CRUD(禁用 scaffold 寫)。

這部份有需要請參考深入淺出 RoR 系列的 4-1 ~ 4-3,當然前面要先看完。

http://rails.pixnet.net/blog/category/list/1603567

2. 附件功能,可使用 plugin 為 paperclip ,下指令 script/plugin install 安裝

http://github.com/thoughtbot/paperclip

裝好之後要按照 plugin 的 READ 做設定,請參考 Qucik Start 的部份

3. 建立 git 管理。先到 github 開新個的 repository ,然後按照 NEXT STEP 的步驟,把 origin master 推上去。

4. 權限控管功能,可使用 plugin 為 restful-authentication ,下指令 script/plugin install 安裝

http://github.com/technoweenie/restful-authentication

裝好之後要按照 plugin 的 READ 做設定,指令為 script/generate authenticated user sessions ,然後要 rake db:migrate

這樣網頁就會多出 login、logout、signup 等頁面

備註:這個 plugin 的功能是放在 lib/authenticated_system.rb

5. 使用者帳號功能裝好後,替各篇文章加上 user_id 的關聯,以及修改、刪除等功能得對應上 user_id 才有執行權限

6. 實作 comment 功能,用 script/generate 新增 comment 用的 controller。這部份直接參考 CRUD 的寫法。

7. 分頁功能,可使用 plugin 為 will_paginate ,下指令 script/plugin install 安裝

http://github.com/mislav/will_paginate

裝好之後不需要設定,直接參考README的範例去寫就可以

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

要寫 Rails 專案,而且想要一次到位,我覺得 git 必學,而且最好跟Rails同時練。

我師父教學時,先從 git 開始教,自己開一個 project 亂搞;github 就去註冊一個帳號,同樣也開 project,想辦法做 push/pull 的動作。

git add, git push, git pull, git commit, git branch, git checkout, git merge, git clone, git stash, git grep

這些都是之後寫 RoR 會常用的指令,先熟悉一下,然後再開始建立 Rails 專案,邊做邊學。

gitx 或 gitk 都是很不錯的圖形化介面,可以看到目前專案的主線、支線、commit 狀況等等;文字介面則有 tig 可以使用。

 

以下是學習可用的相關連結:

git Manual Page

Git 初學文件整理

Git 初學筆記 - 指令操作教學

Git 初學筆記 - 實作測試

Git 原始碼管理 (invalid link)

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()

rake db:create

這是根據config/database.yml內容,直接到資料庫(看你.yml是設定哪種sql)產生database。

但是這樣直接下指令只會對development:之後有反應,如果也想讓test:或是production:的內容產生database,指令範例:

rake db:create RAILS_ENV=production (test自己比照辦理)


==============================

寫RoR的好處是,網路上有許多現成的plugin可以使用,不過要怎麼用呢?

一般而言,建議大家寫RoR搭配git使用(我師父也是這麼教),google之後你會發現很多資源都在github就有

plugin安裝的指令範例:

script/plugin install git://github.com/technoweenie/paperclip.git

切記不要直接下git clone git://github.com/technoweenie/paperclip.git,然後再安裝


==============================

script/destroy可以把script/generate手殘打錯生成的東西清掉。


==============================

有哪些目錄更動後,要重新跑script/server呢?

1. vendor/plugin/

2. lib/(但是裡面的tasks/不用)

3. config

笨笨小蟹 發表在 痞客邦 留言(0) 人氣()