Ruby on Rails 2.x實踐手記

本文爲原創。轉載請註明:
作者:Utensil
博客:http://blog.csdn.net/utensil/
郵箱:[email protected]


這兩天,在將之前那個基於xml和php的博客網站移植到MySQL和ROR上的過程中,攻克了學習ROR的兩個重大難關:

一個是,現在大多數資料講的都是Rails 1.x中的做法,由於2.x打斷了不少向後兼容性(尤其是削去了動態scalffold)
如何在Rails 2.x中做到同樣的事情呢?

第二個是如何在Rails框架之外,使用ActiveRecord訪問數據庫。

這篇文章簡單記錄我對這些問題的探索成果。要感謝Google,但是要憤慨rdoc的文檔形式,以及偶爾有些例子中嚴重的遺漏!希望它能夠越來越完善。

在運行之前,我通過yum安裝的包包括:(我是在Fedora 8下,Ruby是)

ruby.i386
ruby-RMagick.i386
ruby-RMagick-doc.i386
ruby-activerecord.noarch
ruby-activesupport.noarch
ruby-cairo.i386
ruby-devel.i386
ruby-docs.i386  
ruby-fam.i386  
ruby-gdkpixbuf2.i386 
ruby-glib2.i386    
ruby-irb.i386       
ruby-libs.i386     
ruby-mysql.i386  
ruby-rdoc.i386   
ruby-rsvg.i386   
ruby-shadow.i386
ruby-sqlite3.i386  
rubygem-rake.noarch 
rubygems.noarch

加粗了的包較爲重要。有些包,看不出直接的用途,是因爲Dependency自動裝上去的。

Ruby Gem中裝了的包有:

actionmailer (2.1.1)
actionpack (2.1.1)
activerecord (2.1.1)
activeresource (2.1.1)
activesupport (2.1.1)
htmlentities (4.0.0)
rails (2.1.1)
rake (0.8.3, 0.7.3)
rubygems-update (1.3.0)
sources (0.0.1)
xml-simple (1.0.11)

第一個問題:(以不用IDE進行講述,用RadRails的話類似)

cd 你的workspace
rails 你的工程名稱

這時會建了一大堆文件夾和文件,如果你手頭有介紹Rails的書,他會向你介紹它們的結構的。下文用到的路徑,均相對於“你的工程名稱”這個文件夾。

cd 你的工程名稱

現在可以運行

ruby scripts/server

來啓動Ruby內部的服務器,你可以在瀏覽器訪問它報告的那個地址(長得像0.0.0.0:端口號的那個),會看到歡迎界面。

這個時候,你應該去建數據庫了,以一個MySQL的數據庫SusanBlog爲例,假設我們在裏面有這樣一張表:

CREATE TABLE `blogs` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(255) NOT NULL,
  `ctime` datetime default NULL,
  `content` text NOT NULL,
  `latestbak` text,
  `longetbak` text,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

建完之後,就去修改config/database.yml。很簡單易懂,我的yml的Development部分如下:


development:
  adapter: mysql
  encoding: utf8
  database: SusanBlog
  username: root
  password: root的密碼,你自己在MySQL裏設的那個
  socket: /var/lib/mysql/mysql.sock

要非常注意編碼問題,編碼不對可能會導致Rails罷工。yml裏寫的編碼要和數據庫裏的相對應。

yml這一步是scaffold的基石。

接下來可以建立saffold了:

ruby scripts/generate scaffold blog title:varchar ctime:datetime content:text

基本規則是 ruby scripts/generate scaffold 模型名 field:datatype ...

field是你的字段名,datatype是SQL的數據類型。

注意,表名是blogs,是複數,模型名要用單數。假設你的表名是my_items,那麼這裏寫my_item或MyItem都是可以的。

id不用寫,自動增加的,不用用戶指定。`latestbak` text, `longetbak` text,它們由於不一定要非空,所以不用寫。

現在訪問localhost:端口號/blogs就會顯示數據庫中的所有條目,並可以新建,查看,編輯,刪除任何一個條目,這就是傳說中的CRUD了。

可以修改app/views/blogs/裏面的erb模板 (又一個與2.x不同的地方)來改善其界面了,比如我在edit.erb中加入了TinyMCE編輯器:

  1. <h1>編輯日誌</h1>
  2. <%= link_to 'Show', @blog %> |
  3. <%= link_to 'Back', blogs_path %>
  4. <% form_for(@blog) do |f| %>
  5.   <%= f.error_messages %>
  6.   <p>
  7.     <%= f.label :title %><br />
  8.     <%= f.text_field :title %>
  9.   </p>
  10.   <p>
  11.     <%= f.label :ctime %><br />
  12.     <%= f.datetime_select :ctime %>
  13.   </p>
  14.   
  15. <!-- TinyMCE -->
  16. <%= javascript_include_tag "tinymce/jscripts/tiny_mce/tiny_mce" %>
  17. <script type="text/javascript">
  18.     tinyMCE.init({
  19.         // General options
  20.         mode : "textareas",
  21.         theme : "advanced",
  22.         skin : "o2k7",
  23.         plugins : "safari,style,table,save,advhr,advimage,advlink,emotions,inlinepopups,insertdatetime,preview,searchreplace,contextmenu,paste,directionality,fullscreen,visualchars,nonbreaking,xhtmlxtras",
  24.         editor_deselector : "mceNoEditor",
  25.         // Theme options
  26.         theme_advanced_buttons1 : "save,|,undo,redo,|,cut,copy,paste,pastetext,pasteword,|,search,replace,|,formatselect,fontselect,fontsizeselect,styleselect",
  27.         theme_advanced_buttons2 : "bold,italic,underline,strikethrough,|,hr,|,sub,sup,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,forecolor,backcolor,styleprops,|,removeformat,cleanup",
  28.         theme_advanced_buttons3 : "link,unlink,image,charmap,emotions,|,insertdate,inserttime,|,tablecontrols,|,visualaid,visualchars,|,fullscreen,code,preview",
  29.         theme_advanced_toolbar_location : "top",
  30.         theme_advanced_toolbar_align : "left",
  31.         theme_advanced_statusbar_location : "bottom",
  32.         theme_advanced_resizing : true,
  33.         // Example content CSS (should be your site CSS)
  34.         content_css : "css/content.css",
  35.     });
  36. </script>
  37. <!-- /TinyMCE -->
  38.   
  39.   <p>
  40.     <%= f.label :content %><br />
  41.     <%= f.text_area :content,:id=>'elm1'%>
  42.   </p>
  43.   <p>
  44.     <%= f.submit "Update" %>
  45.   </p>
  46. <% end %>

注意<%= javascript_include_tag "tinymce/jscripts/tiny_mce/tiny_mce" %>這一句,這要求你把TinyMCE的文件夾放在public/javascripts下。Rails中對路徑的處理有自己的規則,亂放可能會路由不到。

還可以對index進行排序,在app/models/blogs_controler.rb中的index方法(對,沒有list方法了)中

@blogs = Blog.find(:all)
改成
@blogs = Blog.find(:all, :order => "id DESC")

遺憾的是分頁功能(paginate)被刪除了,好像有第三方庫來做,暫時還沒用過。

第二個問題,索性直接用例子講了,這是我將之前那個xml轉進MySQL的腳本

  1. #!/usr/bin/ruby

  2. require "rexml/document"

  3. require "active_record"

  4. ActiveRecord::Base.establish_connection(
  5. :adapter => "mysql",
  6. :username => "user",
  7. :password => "password",
  8. :database => "SusanBlog",
  9. :host => "localhost",
  10. :encoding => "utf8"
  11. )

  12. class Blog < ActiveRecord::Base
  13. end

  14. file = File.new "./susanblog_original.xml"
  15. blogs = REXML::Document.new file

  16. #也可以用blogs.elements.each("blogs/blog") do |e|,但我需要把整個順序倒過來

  17. ordered = blogs.get_elements("blogs/blog").reverse!

  18. ordered.each do |e|
  19.   Blog.new do |b|
  20.     
  21.     b.title = e.get_text("title").to_s
  22.     b.ctime = e.get_text("timestamp").to_s     #or we can use Time.now.strftime "%Y-%m-%d %H:%M:%S"
  23.     b.content = e.get_text("content").to_s
  24.     
  25.     b.save
  26.   end
  27.   
  28. end
寫這個腳本真是千辛萬苦,文檔太不完善了。注意b.save那一句,文檔中沒有講改完了值還要save,後來經過艱辛的探索才發現要這樣。

使用REXML真是一種痛苦的經歷,建議大家還是用XMLSimple吧,在php裏用的就是它,爽死了。

不過我安裝了xml-simple之後死活require不到,只好自己到/usr/lib/ruby/gem下面把xmlsimple.rb拿出來放在自己腳本旁邊才能用。:( 接下來試試傳說中的Hpricot,似乎更加好。

把這些探索的成果貼出來,希望能方便大家少走彎路。

重大發現:

原來require所有用gems裝的庫在require之前都必須:
  1. require 'rubygems'
一瞬間,好多東西都能用了。那都沒說過啊,直到Hpricot的主頁上,纔有這樣的區分(直接用yum安裝的不用這一步,而用gem裝的則必須。)







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章