作者: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編輯器:
- <h1>編輯日誌</h1>
- <%= link_to 'Show', @blog %> |
- <%= link_to 'Back', blogs_path %>
- <% form_for(@blog) do |f| %>
- <%= f.error_messages %>
- <p>
- <%= f.label :title %><br />
- <%= f.text_field :title %>
- </p>
- <p>
- <%= f.label :ctime %><br />
- <%= f.datetime_select :ctime %>
- </p>
- <!-- TinyMCE -->
- <%= javascript_include_tag "tinymce/jscripts/tiny_mce/tiny_mce" %>
- <script type="text/javascript">
- tinyMCE.init({
- // General options
- mode : "textareas",
- theme : "advanced",
- skin : "o2k7",
- plugins : "safari,style,table,save,advhr,advimage,advlink,emotions,inlinepopups,insertdatetime,preview,searchreplace,contextmenu,paste,directionality,fullscreen,visualchars,nonbreaking,xhtmlxtras",
- editor_deselector : "mceNoEditor",
- // Theme options
- theme_advanced_buttons1 : "save,|,undo,redo,|,cut,copy,paste,pastetext,pasteword,|,search,replace,|,formatselect,fontselect,fontsizeselect,styleselect",
- theme_advanced_buttons2 : "bold,italic,underline,strikethrough,|,hr,|,sub,sup,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,forecolor,backcolor,styleprops,|,removeformat,cleanup",
- theme_advanced_buttons3 : "link,unlink,image,charmap,emotions,|,insertdate,inserttime,|,tablecontrols,|,visualaid,visualchars,|,fullscreen,code,preview",
- theme_advanced_toolbar_location : "top",
- theme_advanced_toolbar_align : "left",
- theme_advanced_statusbar_location : "bottom",
- theme_advanced_resizing : true,
- // Example content CSS (should be your site CSS)
- content_css : "css/content.css",
- });
- </script>
- <!-- /TinyMCE -->
- <p>
- <%= f.label :content %><br />
- <%= f.text_area :content,:id=>'elm1'%>
- </p>
- <p>
- <%= f.submit "Update" %>
- </p>
- <% end %>
還可以對index進行排序,在app/models/blogs_controler.rb中的index方法(對,沒有list方法了)中
把
@blogs = Blog.find(:all)
改成
@blogs = Blog.find(:all, :order => "id DESC")
遺憾的是分頁功能(paginate)被刪除了,好像有第三方庫來做,暫時還沒用過。
第二個問題,索性直接用例子講了,這是我將之前那個xml轉進MySQL的腳本
- #!/usr/bin/ruby
- require "rexml/document"
- require "active_record"
- ActiveRecord::Base.establish_connection(
- :adapter => "mysql",
- :username => "user",
- :password => "password",
- :database => "SusanBlog",
- :host => "localhost",
- :encoding => "utf8"
- )
- class Blog < ActiveRecord::Base
- end
- file = File.new "./susanblog_original.xml"
- blogs = REXML::Document.new file
- #也可以用blogs.elements.each("blogs/blog") do |e|,但我需要把整個順序倒過來
- ordered = blogs.get_elements("blogs/blog").reverse!
- ordered.each do |e|
- Blog.new do |b|
- b.title = e.get_text("title").to_s
- b.ctime = e.get_text("timestamp").to_s #or we can use Time.now.strftime "%Y-%m-%d %H:%M:%S"
- b.content = e.get_text("content").to_s
- b.save
- end
- end
使用REXML真是一種痛苦的經歷,建議大家還是用XMLSimple吧,在php裏用的就是它,爽死了。
不過我安裝了xml-simple之後死活require不到,只好自己到/usr/lib/ruby/gem下面把xmlsimple.rb拿出來放在自己腳本旁邊才能用。:( 接下來試試傳說中的Hpricot,似乎更加好。
把這些探索的成果貼出來,希望能方便大家少走彎路。
重大發現:
原來require所有用gems裝的庫在require之前都必須:
- require 'rubygems'