Selected Category: ROR (5)

View Mode: Post List Post Summary

save 可以接收一個參數 :perform_validation => true/false,預設為 true。
當 perform_validation 被設為 false 時不會過 validation.

save! 沒有任何額外參數,一定會過 validation.

在執行 save 時,如果有任一個 before_* validation 失敗,整個 save 會回傳 false。

而在執行 save! 時,before_* validation 失敗則是會丟一個例外 ActiveRecord::RecordNotSaved 回來。

所以在應用上:

  • 在 controller 裡一般使用 save,免得每一個 save 失敗都要做 rescue,因為使用者的輸入錯誤是很自然會發生的;
  • 而在像是 rake 或 test 中,就應該使用 save!,方便 debug.

 

參考:Rails API - Class:ActiveRecord::Base#save

Posted by Manic at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(75)

這篇文章講的很清楚:attributes= (ActiveRecord::Base) - APIdock

這樣要繞過 attr_protected 的 column 時就不用一個一個手動指定了。

Posted by Manic at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(100)

1. 使用 Model.increment_counter(counter_name, id):

003:0> User.increment_counter(:hit_counter, 1)
User Update (0.8ms)   UPDATE `users` SET `hit_counter` = COALESCE(`hit_counter`, 0) + 1 WHERE (`id` = 1)

2. 使用 Model.update_counters(id, attribute => ammount)

011:0> User.update_counters(1, :hit_counter => 50)
User Update (0.7ms)   UPDATE `users` SET `hit_counter` = COALESCE(`hit_counter`, 0) + 50 WHERE (`id` = 1)

第1個方法可以單純的做+1動作,第2個方法多了指定要加多少。

另外,Rails 還有一個 instance method: increment,但我其實不建議使用它。因為他不是用 sql 的加法來達成 incrment.

013:0> user = User.first
014:0> user.increment(:hit_counter, 2)
015:0> user.save
User Update (0.2ms)   UPDATE `users` SET `updated_at` = '2009-10-26 04:09:00', `hit_counter` = 163 WHERE `id` = 1

這種方式有可能出現 race condition.

Posted by Manic at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(75)

這裡主要是講 database 使用 mysql 的狀況。

在 Rails 裡,對於 text 的指定只有一種。

而有時我們需要更大的欄位,比方說 medium text, big text。因為有時候,大一點還是比較好。

這時候在 migration 裡的作法有兩種個方式:

第一種是以指定 limit 大小的方式讓 mysql 自行將欄位設定為 medium text (請注意 "content" ):

  1. class CreateArticles < ActiveRecord::Migration
  2.   def self.up
  3.     create_table :articles do |t|
  4.       t.string    :title
  5.       t.text      :content, :limit => 64.kilobytes + 1
  6.       t.timestamps
  7.     end
  8.   end
  9.  
  10.   def self.down
  11.     drop_table :articles
  12.   end
  13. end
  14.  

第二種是在 self.up 後再 exeucte 自行生成你要的欄位:

  1. class CreateArticles < ActiveRecord::Migration
  2.   def self.up
  3.     create_table :articles do |t|
  4.       t.string    :title
  5.       t.timestamps
  6.     end
  7.     execute "ALTER TABLE articles ADD `content` MEDIUMTEXT NOT NULL AFTER `title`"
  8.   end
  9.  
  10.   def self.down
  11.     drop_table :articles
  12.   end
  13. end

Posted by Manic at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(101)

在 Rails 裡對做 CRUD 時,有個方便的實作。

params 表示 form parameters,為 hash 型式 (column => value),這樣子若要把 form 的資料接過來只需要一行。

除了 new 之外,還支援這樣的方式:

方便歸方便,但也衍生了一個問題,那就是使用者的 form 表單裡塞了一些我們不希望被修改的 column 時,這些指令依然會被執行。

比方說帳號欄位,我們通常是不希望被修改的。

於是這時候可以使用 attr_accessible 或 attr_protected 來保護這些欄位

attr_protected :account

這樣在使用 new, attributes=(attributes), update_attributes(attributes) 時,account 欄位會被保護,不被這些 method 改變其值。

而如果我們真的要改變的話,需要自行指定。

以下是 Rails api 給的範例,可以更清楚我在講什麼

Posted by Manic at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(123)