<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cyberpunk &#187; ActiveRecord</title>
	<atom:link href="http://punk.tw/tag/activerecord/feed" rel="self" type="application/rss+xml" />
	<link>http://punk.tw</link>
	<description>網際叛客：學習心得、Web 2.0與網路觀察、Google應用與技術、Ruby on Rails, Google App Engine</description>
	<lastBuildDate>Tue, 07 Feb 2012 08:42:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>在Rails 2.0中如何避免在URL使用資料流水號</title>
		<link>http://punk.tw/2008/04/29/%e5%9c%a8rails-20%e4%b8%ad%e5%a6%82%e4%bd%95%e9%81%bf%e5%85%8d%e5%9c%a8url%e4%bd%bf%e7%94%a8%e8%b3%87%e6%96%99%e6%b5%81%e6%b0%b4%e8%99%9f</link>
		<comments>http://punk.tw/2008/04/29/%e5%9c%a8rails-20%e4%b8%ad%e5%a6%82%e4%bd%95%e9%81%bf%e5%85%8d%e5%9c%a8url%e4%bd%bf%e7%94%a8%e8%b3%87%e6%96%99%e6%b5%81%e6%b0%b4%e8%99%9f#comments</comments>
		<pubDate>Mon, 28 Apr 2008 19:23:18 +0000</pubDate>
		<dc:creator>deduce</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>

		<guid isPermaLink="false">http://punk.tw/2008/04/29/857.html</guid>
		<description><![CDATA[<p>我曾寫過一篇「<a href="http://punk.tw/2007/10/06/340.html">Rails: 建立Permalink，避免流水號洩漏網站資料</a>」針對有人擔心（或質疑）Ruby on Rails中以資料表主鍵流水號作為URL中的參數，會導致網站洩漏某些不希望被外界一眼看穿的資訊，例如使用者總數或文章總數之類的數據，因此簡單地透過Model在存取資料庫時的before_create方法建立每一筆資料的unique key來避免這個問題。</p> ]]></description>
			<content:encoded><![CDATA[<p>我曾寫過一篇「<a href="http://punk.tw/2007/10/06/340.html">Rails: 建立Permalink，避免流水號洩漏網站資料</a>」針對有人擔心（或質疑）Ruby on Rails中以資料表主鍵流水號作為URL中的參數，會導致網站洩漏某些不希望被外界一眼看穿的資訊，例如使用者總數或文章總數之類的數據，因此簡單地透過Model在存取資料庫時的before_create方法建立每一筆資料的unique key來避免這個問題。</p>
<p>之前使用Rails 1.2.x版本時根據我當時的作法並無不妥，因為我自己的coding習慣是會完整地指定controller, action以及id，並在對應的action中使用find_by_key的方法來找到資料。</p>
<p>然而，升級到Rails 2.0後便會出現許多麻煩，例如預設產生的scaffold必須修改許多地方，才能讓Model.find_by_key、redirect_to <strong>post_url</strong>(@post)之類的方法正確運作。</p>
<p>於是我一直到前陣子才找到應該比較正規的作法：在Model中使用to_param方法。</p>
<p>to_param(): Enables Active Record objects to be used as URL parameters in Action Pack automatically.</p>
<p>這麼好用的方法我居然不是一開始就發現，只能說相見恨晚，好險我開發Rails 2.0的時間還不算長，沒走到太多冤枉路。要實踐本標題所說的在Rails 2.0中如何避免在URL使用資料流水號便相當簡單！</p>
<p>1. 建立Scaffold：（通常會對key這個欄位建立index並設定字串長度limit，別忘了:p）<br />script/generate post title:string content:text key:string</p>
<p>2. 將Post的migration寫進資料庫後修改Post model如下：</p>
<p>
<pre class="prettyprint">
class Post < ActiveRecord::Base
  before_create :generate_key

<strong>  def self.find(*args)
    if args.first.is_a?(String)
      find_by_key(args.shift, *args) or raise ActiveRecord::RecordNotFound
    else
      super
    end
  end

  def to_param
    key
  end</strong>

  protected
  # 我前一篇文章產生key的方式不太一樣，這應該是個人習慣。
  # 另外，其實亂碼的網址沒有SEO的效益，建議還是弄個slug吧！
  def generate_key
    require 'digest/sha1'
    self.key = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )[15..24]
  end
end
</pre>
</p>
<p>就這樣！<strong>概念很簡單，就是不再用ID當查詢的參數，全面改用key</strong>啦！關鍵就在於使用to_param()方法以及對find做進一步的判斷，因為我<strong>除了Model.find(:all)之類的Symbol，其餘的CRUD都是傳入Key作為參數</strong>，因此在此僅簡單地判斷是否為字串。</p>
<p>如此一來，不管你是什麼user_posts_url, new_user_post_url都可以輕鬆地直接以ActiveRecord Object傳遞，起碼我之前曾經嘗試用edit_post_url(@post.key)這種方式傳值，非常麻煩、要改Controller又要改View，現在用了to_param()，什麼都不用改了！又優雅又簡單，寫起來更加快樂、效率也提昇了:p</p>
<p>P.S. 其實在Rails 1.2.x應該也是這麼做比較優雅，不限於2.0</p>
]]></content:encoded>
			<wfw:commentRss>http://punk.tw/2008/04/29/%e5%9c%a8rails-20%e4%b8%ad%e5%a6%82%e4%bd%95%e9%81%bf%e5%85%8d%e5%9c%a8url%e4%bd%bf%e7%94%a8%e8%b3%87%e6%96%99%e6%b5%81%e6%b0%b4%e8%99%9f/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails: 建立多對多關係（M:N）</title>
		<link>http://punk.tw/2007/11/11/rails-%e5%bb%ba%e7%ab%8b%e5%a4%9a%e5%b0%8d%e5%a4%9a%e9%97%9c%e4%bf%82%ef%bc%88mn%ef%bc%89</link>
		<comments>http://punk.tw/2007/11/11/rails-%e5%bb%ba%e7%ab%8b%e5%a4%9a%e5%b0%8d%e5%a4%9a%e9%97%9c%e4%bf%82%ef%bc%88mn%ef%bc%89#comments</comments>
		<pubDate>Sun, 11 Nov 2007 13:57:43 +0000</pubDate>
		<dc:creator>deduce</dc:creator>
				<category><![CDATA[Ruby on Rails學習筆記]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://punk.tw/2007/11/11/397.html</guid>
		<description><![CDATA[前陣子寫了兩篇關於建立好友名單的文章：Rails: 建立好友名單、Rails: 建立好友名單（續）加上好友描述，文中有提到，除非有特殊需求，否則建議建立多對多關係請盡量使用has_and_belongs_to_many(habtm)或has_many :through的方式來建立。 我個人比較常用到的是has_many :through，也就是本篇的主題。 範例說明 本範例將建立物品清單管理，每個使用者擁有多個物品，例如A擁有電腦、手機、相機；使用者設定物品清單的時候可以建立描述，例如紀錄購入時間、價格或是其他文字描述等等。 資料庫規劃 首先建立兩個Model分別為User、Item，分別對應到Users以及Items資料表，另外建立記錄兩者relationship的Model及Table，使用migration來建立內容如下： # db/migrate/001_create_users.rb class CreateUsers < ActiveRecord::Migration def self.up create_table :users do &#124;t&#124; t.column :name, :string, :null => false t.column :created_at, :datetime end end def self.down drop_table :users end end # db/migrate/002_create_items.rb class CreateItems < ActiveRecord::Migration def self.up create_table :items do &#124;t&#124; t.column :name, :string, :null [...]]]></description>
			<content:encoded><![CDATA[<p>前陣子寫了兩篇關於建立好友名單的文章：<a href="http://punk.tw/2007/10/06/341.html">Rails: 建立好友名單</a>、<a href="http://punk.tw/2007/10/06/342.html">Rails: 建立好友名單（續）加上好友描述</a>，文中有提到，除非有特殊需求，否則建議建立多對多關係請盡量使用has_and_belongs_to_many(habtm)或has_many :through的方式來建立。</p>
<p>我個人比較常用到的是has_many :through，也就是本篇的主題。</p>
<h1>範例說明</h1>
<p>本範例將建立物品清單管理，每個使用者擁有多個物品，例如A擁有電腦、手機、相機；使用者設定物品清單的時候可以建立描述，例如紀錄購入時間、價格或是其他文字描述等等。</p>
<h1>資料庫規劃</h1>
<p>首先建立兩個Model分別為User、Item，分別對應到Users以及Items資料表，另外建立記錄兩者relationship的Model及Table，使用migration來建立內容如下：</p>
<p>
<pre class="prettyprint"># db/migrate/001_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.column :name, :string, :null => false
      t.column :created_at, :datetime
    end
  end

  def self.down
    drop_table :users
  end
end

# db/migrate/002_create_items.rb
class CreateItems < ActiveRecord::Migration
  def self.up
    create_table :items do |t|
      t.column :name, :string, :null => false
      t.column :description, :text
      t.column :created_at, :datetime
    end
  end

  def self.down
    drop_table :items
  end
end

# db/migrate/003_create_ownerships.rb
class CreateOwnerships < ActiveRecord::Migration
  def self.up
    create_table <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships do |t|
      t.column :user_id, :integer, :null => false
      t.column :item_id, :integer, :null => false
      t.column :description, :text
      t.column :created_at, :datetime
      t.column :updated_at, :datetime
    end
  end

  def self.down
    drop_table <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships
  end
end
</pre>
<p>
Model的程式如下，簡單來說就是透過第三個Model來記錄兩個Model之間的關係：</p>
<pre class="prettyprint">
# app/models/item.rb
class Item < ActiveRecord::Base
  has_many <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships
  has_many :users, :through => <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships
end

# app/models/user.rb
class User < ActiveRecord::Base
  has_many <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships
  has_many :items, :through => <img src='http://punk.tw/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> wnerships
end

# app/models/ownership.rb
class Ownership < ActiveRecord::Base
  belongs_to :item
  belongs_to :user
end
</pre>
</p>
<p>
如此一來，就可以用下列指令來增加User, Item，並且可以查詢到某User所有的items，或是<br />
擁有某item的users。</p>
<pre class="prettyprint">
peter = User.create(:name => "Peter")

deduce = User.create(:name => "Deduce")

phone = Item.create(:name => "phone")
camera = Item.create(:name => "camera")

peter.items << phone

peter.items.count
phone.users.count
</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://punk.tw/2007/11/11/rails-%e5%bb%ba%e7%ab%8b%e5%a4%9a%e5%b0%8d%e5%a4%9a%e9%97%9c%e4%bf%82%ef%bc%88mn%ef%bc%89/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails: 建立好友名單（續）加上好友描述</title>
		<link>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae%ef%bc%88%e7%ba%8c%ef%bc%89%e5%8a%a0%e4%b8%8a%e5%a5%bd%e5%8f%8b%e6%8f%8f%e8%bf%b0</link>
		<comments>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae%ef%bc%88%e7%ba%8c%ef%bc%89%e5%8a%a0%e4%b8%8a%e5%a5%bd%e5%8f%8b%e6%8f%8f%e8%bf%b0#comments</comments>
		<pubDate>Sat, 06 Oct 2007 13:48:14 +0000</pubDate>
		<dc:creator>deduce</dc:creator>
				<category><![CDATA[Ruby on Rails學習筆記]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://punk.tw/2007/10/06/342.html</guid>
		<description><![CDATA[前言 這篇文章你可以視為「如何在多對多關係中，記錄額外的資訊」。其實一般想要在M:N之間的關係記錄額外的資訊，應該是會透過has_many :through比較恰當，不過因為當初我在寫好友名單時，先用了上一篇文章的寫法，所以才找到本篇文章要談的作法。 簡單來說，如果要記錄的資訊只有一個欄位，用本篇作法是快又有效；否則，我認為還是用has_many :through應該比較方便。後者的作法下次再談。 正文開始... 常見的社群網站，建立好友之間的關係不外乎是加入好友、並通知對方，似乎比較少有可以替好友分群組、加上描述的功能，其中丁丁大站就是可以替好友們加上描述以及分組的。這篇文章就是教你如何像丁丁大站一樣，用簡單的程式建立好友關係並加上簡單的描述。 首先一樣是你必須有一張記錄Friendship的Table，偷用上一篇的Migration（這樣上一篇瞬間變得毫無意義了-.-，不過我的想法是，一般人應該只會用到上一篇的作法。）。注意，與上一篇不同的是，這裡多了description欄位 class AddFriendship < ActiveRecord::Migration def self.up create_table :friendships, :id => false do &#124;t&#124; t.column :user_id, :integer, :null => false t.column :friend_id, :integer, :null => false t.column :description :string end end def self.down drop_table :friendships end end 接下來一樣是定義model，一樣是拿上一篇的程式，多了三行程式： attr_accessor :description，由於ActiveRecord的Class在mapping到資料庫時，是直接對應到table的column，但目前users table沒有description這個column，因此我們在此給User這個class一個屬性，等一下在建立好友關係時就可以一併連好友描述都塞到friendships裡面。 :insert_sql，因為除了ActiveRecord會幫我們找到foreign_key所屬的欄位之外，我們還需要塞入額外的資訊，因此自訂語法。 after_find的定義，由於ActiveRecord撈出資料後，User這個model本身沒有description欄位，所以我們在撈出好友關係的時候，再把description寫到剛剛建立好的屬性。 class User < ActiveRecord::Base attr_accessor [...]]]></description>
			<content:encoded><![CDATA[<h1>前言</h1>
<p>這篇文章你可以視為「如何在多對多關係中，記錄額外的資訊」。其實一般想要在M:N之間的關係記錄額外的資訊，應該是會透過has_many :through比較恰當，不過因為當初我在寫好友名單時，先用了<a href="http://punk.tw/2007/10/06/341.html">上一篇文章</a>的寫法，所以才找到本篇文章要談的作法。</p>
<p>簡單來說，如果要記錄的資訊只有一個欄位，用本篇作法是快又有效；否則，我認為還是用has_many :through應該比較方便。後者的作法下次再談。</p>
<h1>正文開始...</h1>
<p>常見的社群網站，建立好友之間的關係不外乎是加入好友、並通知對方，似乎比較少有可以替好友分群組、加上描述的功能，其中丁丁大站就是可以替好友們加上描述以及分組的。這篇文章就是教你如何像丁丁大站一樣，用簡單的程式建立好友關係並加上簡單的描述。</p>
<p>首先一樣是你必須有一張記錄Friendship的Table，偷用上一篇的Migration（這樣<a href="http://punk.tw/2007/10/06/341.html">上一篇</a>瞬間變得毫無意義了-.-，不過我的想法是，一般人應該只會用到<a href="http://punk.tw/2007/10/06/341.html">上一篇</a>的作法。）。注意，與<a href="http://punk.tw/2007/10/06/341.html">上一篇</a>不同的是，這裡多了description欄位</p>
<pre class="prettyprint">class AddFriendship < ActiveRecord::Migration
  def self.up
    create_table :friendships, :id => false do |t|
      t.column :user_id, :integer, :null => false
      t.column :friend_id, :integer, :null => false
      t.column :description :string
    end
  end

  def self.down
    drop_table :friendships
  end
end</pre>
<p>接下來一樣是定義model，一樣是拿上一篇的程式，多了三行程式：</p>
<ul>
<li>attr_accessor :description，由於ActiveRecord的Class在mapping到資料庫時，是直接對應到table的column，但目前users table沒有description這個column，因此我們在此給User這個class一個屬性，等一下在建立好友關係時就可以一併連好友描述都塞到friendships裡面。</li>
<li>:insert_sql，因為除了ActiveRecord會幫我們找到foreign_key所屬的欄位之外，我們還需要塞入額外的資訊，因此自訂語法。</li>
<li>after_find的定義，由於ActiveRecord撈出資料後，User這個model本身沒有description欄位，所以我們在撈出好友關係的時候，再把description寫到剛剛建立好的屬性。</li>
</ul>
<pre class="prettyprint">
class User < ActiveRecord::Base
  attr_accessor :description
  has_and_belongs_to_many :friends,
    :class_name => "User",
    :join_table => "friendships",
    :association_foreign_key => "friend_id",
    :foreign_key => "user_id",
    :insert_sql => 'INSERT into friendships (user_id, friend_id, description) VALUES (#{id}, #{record.id}, \'#{record.description}\')'
    # 要特別注意引號的使用，尤其description通常都是string，所以用單引號框起來

  def after_find
    self.description = self["description"]
    # <del datetime="2007-10-06T14:06:59+00:00">說實在這邊我也不是很確定寫法是否正確XD</del>應該說可以work，但不知道有沒有更好的寫法:p
  end
end
</pre>
<p>如此一來，你就可以用下列的程式來建立、取得好友及描述</p>
<pre class="prettyprint">
u = User.create(:name => "deduce")
k = User.create(:name => "punk")
u.description = "Rails愛好者:deduce"
k.friends <<  u unless k.friends.include?(u)

# 輸出好友描述
k.friends.each do |friend|
  puts friend.description
end
</pre>
<p>註：description的字串丟進去之前要記得先處理，避免發生不必要的問題，例如SQL injection之類的。
</p>
<h1>References</h1>
<ul>
<li><a href="http://punk.tw/2007/10/06/341.html">Rails: 建立好友名單</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae%ef%bc%88%e7%ba%8c%ef%bc%89%e5%8a%a0%e4%b8%8a%e5%a5%bd%e5%8f%8b%e6%8f%8f%e8%bf%b0/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Rails: 建立好友名單</title>
		<link>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae</link>
		<comments>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae#comments</comments>
		<pubDate>Sat, 06 Oct 2007 11:59:16 +0000</pubDate>
		<dc:creator>deduce</dc:creator>
				<category><![CDATA[Ruby on Rails學習筆記]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://punk.tw/2007/10/06/341.html</guid>
		<description><![CDATA[網站想要開發「好友名單」功能時，會新增Table來記錄好友之間的關係，在Rails應該怎麼做呢？假設目前系統已經有User這個Model，我們將會建立 User has_many friends的關係來記錄每個User擁有的好友們。 首先新增一張Table來記錄Friendship（請善用Migration）： class AddFriendship < ActiveRecord::Migration def self.up create_table :friendships, :id => false do &#124;t&#124; t.column :user_id, :integer, :null => false t.column :friend_id, :integer, :null => false end end def self.down drop_table :friendships end end 接下來在User Model中定義好友關係： class User < ActiveRecord::Base has_and_belongs_to_many :friends, :class_name => "User", :join_table => "friendships", :association_foreign_key => "friend_id", [...]]]></description>
			<content:encoded><![CDATA[<p>網站想要開發「好友名單」功能時，會新增Table來記錄好友之間的關係，在Rails應該怎麼做呢？假設目前系統已經有User這個Model，我們將會建立 User has_many friends的關係來記錄每個User擁有的好友們。</p>
<p>首先新增一張Table來記錄Friendship（請善用Migration）：</p>
<p>
<pre class="prettyprint">class AddFriendship < ActiveRecord::Migration
  def self.up
    create_table :friendships, :id => false do |t|
      t.column :user_id, :integer, :null => false
      t.column :friend_id, :integer, :null => false
    end
  end

  def self.down
    drop_table :friendships
  end
end</pre>
</p>
<p>接下來在User Model中定義好友關係：
<pre class="prettyprint">
class User < ActiveRecord::Base
  has_and_belongs_to_many :friends,
    :class_name => "User",
    :join_table => "friendships",
    :association_foreign_key => "friend_id",
    :foreign_key => "user_id"
end
</pre>
</p>
<p>如此一來，你就可以用下列語法來建立使用者之間的好友關係：
<pre class="prettyprint">u = User.create(:name => "deduce")
k = User.create(:name => "punk")
u.friends << k if not u.friends.include?(k)
# 如果 u 的好友不包含 k 則加入好友，不需要另外進行儲存的動作
</pre>
</p>
<p>u.friends取得好友名單、u.friends.count取得好友人數</p>
]]></content:encoded>
			<wfw:commentRss>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8b%e5%a5%bd%e5%8f%8b%e5%90%8d%e5%96%ae/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Rails: 建立Permalink，避免流水號洩漏網站資料</title>
		<link>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8bpermalink%ef%bc%8c%e9%81%bf%e5%85%8d%e6%b5%81%e6%b0%b4%e8%99%9f%e6%b4%a9%e6%bc%8f%e7%b6%b2%e7%ab%99%e8%b3%87%e6%96%99</link>
		<comments>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8bpermalink%ef%bc%8c%e9%81%bf%e5%85%8d%e6%b5%81%e6%b0%b4%e8%99%9f%e6%b4%a9%e6%bc%8f%e7%b6%b2%e7%ab%99%e8%b3%87%e6%96%99#comments</comments>
		<pubDate>Sat, 06 Oct 2007 10:11:37 +0000</pubDate>
		<dc:creator>deduce</dc:creator>
				<category><![CDATA[Ruby on Rails學習筆記]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://punk.tw/2007/10/06/340.html</guid>
		<description><![CDATA[XDite曾經在「以 ROR 打造網站，設計盲點所引發的惡搞危機」這篇文章中提到Rails的scaffold所建立出來的程式（或說開發者很習慣直接以id操作Model），由於在URL上是直接以流水號的方式呈現，我們便可以利用一些簡單的程式爬完某個網站的特定頁面，來取得所有的文章、所有的使用者頁面。 事實上XDite應該是有在另外一場活動提過因應的對策，雖然我沒抓下來聽，不過我猜應該是改變Controller的設計方式，以亂碼或是其他方式來產生URL。 首先在Table裡面加上「permalink」這個column，如果你是要在既有的table上新增，可以使用migration來新增欄位（當然你也可以砍掉重練XD） class AddPermalink < ActiveRecord::Migration def self.up add_column :posts, :permalink, :string add_index :posts, :permalink, :unique => true end def self.down remove_index :posts, :permalink remove_column :posts, :permalink end end 接下來在Model裡面定義permalink的產生方式 class Post < ActiveRecord::Base before_create :generate_permalink protected def generate_permalink # 定義permalink的產生方式 self.permalink = Time.now.strftime("%Y-%m-%d_") + rand(100000).to_s end end 這邊我是用時間加亂數的方式產生permalink，事實上這樣的寫法還是有可能重複，不如用SHA或MD5的方式來產生Permalink也不錯（雖然長了點）。 class Post < [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.xdite.net/">XDite</a>曾經在「<a href="http://blog.xdite.net/?p=424">以 ROR 打造網站，設計盲點所引發的惡搞危機</a>」這篇文章中提到Rails的scaffold所建立出來的程式（或說開發者很習慣直接以id操作Model），由於在URL上是直接以流水號的方式呈現，我們便可以利用一些簡單的程式爬完某個網站的特定頁面，來取得所有的文章、所有的使用者頁面。</p>
<p>事實上XDite應該是有在另外一場活動提過<a href="http://lukhnos.org/blog/zh/archives/551">因應的對策</a>，雖然我沒抓下來聽，不過我猜應該是改變Controller的設計方式，以亂碼或是其他方式來產生URL。</p>
<p>首先在Table裡面加上「permalink」這個column，如果你是要在既有的table上新增，可以使用migration來新增欄位（當然你也可以砍掉重練XD） </p>
<p>
<pre class="prettyprint">class AddPermalink < ActiveRecord::Migration
  def self.up
    add_column :posts, :permalink, :string
    add_index :posts, :permalink, :unique => true
  end

  def self.down
    remove_index :posts, :permalink
    remove_column :posts, :permalink
  end
end
</pre>
<p>接下來在Model裡面定義permalink的產生方式
<pre class="prettyprint">class Post < ActiveRecord::Base
  before_create :generate_permalink

  protected
    def generate_permalink
      # 定義permalink的產生方式
      self.permalink = Time.now.strftime("%Y-%m-%d_") + rand(100000).to_s
    end
end</pre>
</p>
<p>這邊我是用時間加亂數的方式產生permalink，事實上這樣的寫法還是有可能重複，不如用SHA或MD5的方式來產生Permalink也不錯（雖然長了點）。
<pre class="prettyprint">class Post < ActiveRecord::Base
  before_create :generate_permalink

  protected
    def generate_permalink
      # 用標題+時間進行md5的編碼
      require 'digest/md5'
      self.permalink = Digest::MD5.hexdigest(self.title + Time.now.to_s)
    end
end
</pre>
<p>往後在連結可以使用： </p>
<pre class="prettyprint"> link_to post.title,
                :controller => "post",
                :action => "show",
                :id => post.permalink
</pre>
<p>在Controller裡面Action的寫法則是：
<pre class="prettyprint">class PostController < ApplicationController
  def show
    @post = Post.find_by_permalink(params[:id])
  end
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://punk.tw/2007/10/06/rails-%e5%bb%ba%e7%ab%8bpermalink%ef%bc%8c%e9%81%bf%e5%85%8d%e6%b5%81%e6%b0%b4%e8%99%9f%e6%b4%a9%e6%bc%8f%e7%b6%b2%e7%ab%99%e8%b3%87%e6%96%99/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

