程序员…
24 May
有的时候,虚拟主机提供商并不能按照每个用户的需求安装全部的gem,这个时候,我们就需要自己动手了,如下是我在一家虚拟主机上的安装builder的过程,主要就是先FTP把gem包放上去,然后本地安装的时候使用一个–install-dir来指定安装到的目录。<code>[1ster@1ster.cn@bee-00 gemdir]$ gem install builder-2.1.1.gem –install-dir /var/***/***/1ster.cn/gemdirSuccessfully installed builder, version 2.1.1Installing ri documentation for builder-2.1.1…Installing RDoc documentation for builder-2.1.1…</code>
23 May
我们使用创建表的时候,是不想想初始化一些数据呢,比如一个默认的分类什么的,可以使用migration按照下面这个来实现: <code> def self.up create_table :words do |t| t.column :eng, :string t.column :pl, :string end Word.new(:eng=>’yes’, :pl=>’tak’).save Word.new(:eng=>’no’, :pl=>’nie’).save Word.new(:eng=>’everything’, :pl=>’wszystko’).save end def self.down drop_table :words end</code>
23 May
题外话:这个文章展示了一种测试驱动(TDD)的开发模式,针对Rails的基本步骤,原文很清楚,我就随便翻译下关键的部分,见下:原文地址:http://andrzejonsoftware.blogspot.com/2007/05/15-tdd-steps-to-create-rails.html15 TDD steps to create a Rails applicationIntroductionSeveral times recently, I have been asked how to develop a Rails application using the Test Driven Development approach. I’m not an expert here, but I’ve put together some notes on how to start working on a Rails application whilst being test-driven all the time.As an example I will use a word-learning web application. The simplest use case is to display a random word object (with its polish translation) from the database.Every time we refresh we want to see a different word.1. Create a new Rails applicationsrails my_appcd my_appRun tests with ‘rake test’. It fails due to missing database configuration.2. Set up the databases – config/database.ymlThe code below assumes sqlite3 databases. development: adapter: sqlite3 database: db/my_app_development.sqlite test: adapter: sqlite3 database: db/my_app_test.sqlite’rake test’ now runs fine.3. Create a Word class with a corresponding unit testscript/generate model Word4. Write a unit test for the Word class. Edit the test/unit/word_test.rb. def test_word_is_english_and_polish word = Word.new :eng=>’never’, :pl=>’nigdy’ assert_equal ‘never’, word.eng assert_equal ‘nigdy’, word.pl end’rake test’ now fails due to missing words table.5. Edit db/migrate/001_create_words.rbWe are using a migration here in order to create a table. It’s a recommended way of dealing with database changes. def self.up create_table :words do |t| t.column :eng, :string t.column :pl, :string end Word.new(:eng=>’yes’, :pl=>’tak’).save Word.new(:eng=>’no’, :pl=>’nie’).save Word.new(:eng=>’everything’, :pl=>’wszystko’).save end def self.down drop_table :words endThe sample words that we are adding use Word.new .. lines, will be added to the development database. It’s important to distinguish the ‘test’ and ‘development’ database. The first one is only used during tests. The latter is used by default when you start the application.Apply the migration with ‘rake db:migrate’.'rake test’ now succeeds with the following:’1 tests, 2 assertions, 0 failures, 0 errors’6. Fixtures and test for word.random. Edit word_test again.It’s not easy to test a method which behaves randomly. Let’s assume that it’s enough to test that if we have only two words in our database then one of them should be called at least once per 10 calls.fixtures :wordsdef test_random results = [] 10.times {results << Word.random.eng} assert results.include?("yes")endNote the ‘fixtures :words’ line. Edit the ‘words.yml’ file.yes: id: 1 pl: ‘tak’ eng: ‘yes’no: id: 2 pl: ‘nie’ eng: ‘no’This will be loaded to the test database before every run of tests.7. Implement the Word.random method def self.random all = Word.find :all all[rand(all.size)] endWarning: The code above could be slow for many words in a database (we retrieve all words only for selecting a random element). It’s good enough for our needs.8. Generate the Words controller with a ‘learn’ actionscript/generate controller Words learn9. Write a test for the learn methodJust as there is a one-to-one ratio between unit tests and models, so there is between functional tests and controllers. The Controller’s responsibility is to retrieve objects from the Model layer and pass them to the View. Let’s test the View part first. We use the ‘assigns’ collection which contains all the objects passed to the View.def test_learn_passes_a_random_word get ‘learn’ assert_kind_of Word, assigns(‘word’)end10. Make the Test Passdef learn @word = Word.newend11. Write more tests in the words_controller_testHow can we test that controller uses the Word.random method? We don’t want to duplicate the tests for the Word.random method.Mocks to the rescue! We will only test that the controller calls the Word.random method. The returned value will be faked with a prepared word.Let’s install the mocha framework:gem install mochaNow we can use ‘expects’ and ‘returns’ methods.’expects’ is used for setting an expectation on an object or a class. In this case we expect that the ‘random’ method will be called. We also set a return value by using ‘returns’ method. Setting a return value means faking (stubbing) the real method. The real Word.random won’t be called. If an expectation isn’t met the test fails.require ‘mocha’def test_learn_passes_a_random_word random_word = Word.new Word.expects(:random).returns(random_word) get ‘learn’ assert_equal random_word, assigns(‘word’)end’rake test’ now fails. The Word.method wasn’t called.12. Rewrite the implementationdef learn @word = Word.randomend’rake test’ now passes.13. Test that a word is displayed:Extend the existing test with assert_tag calls.def test_learn_passes_a_random_word random_word = Word.new(:pl=>’czesc’, :eng=>’hello’) Word.expects(:random).returns(random_word) get ‘learn’ assert_equal random_word, assigns(‘word’) assert_tag :tag=>’div’, :child => /czesc/ assert_tag :tag=>’div’, :child => /hello/end14. Implement the view – learn.rhtml <div> <%= word.eng %> <%= word.pl %> </div>15. Manual testingscript/serverGo to ‘http://localhost:3000/words/learn’.Refresh several times.If you want to read more about testing in Rails go to the Guide To Testing The Rails.
22 May
题外话: 学习ROR这么久了,也没有时间仔细整理下到底学会了什么,今天一个朋友想招几个ROR的程序员,让我帮忙出几个题目,结合自己学的,也邀请了对岸的兄弟CFC帮忙,一起整理了以下这些问题,可能还不够严谨,有好的建议请提哈!有时间的可以对照着问题看看自己的答案是什么,欢迎留言!一、热身题1、ROR是什么的简写?2、你多大了,从你接触ROR到现在大概有多少时间了?3、你学习ROR之前还学习过哪些语言?为什么会来学ROR呢?4、你接触ROR后,被它的哪些特性(或者说哪些和别的语言不一样的地方)打动过呢?5、列举几个你了解的开源ROR项目?他们各自都是做什么的?二、基础题6. 现有一个User Model,我想要查ID为10, 30, 36三笔数据,请问如何做?7. 现有一个User Model,内有username、password两个字段,我想要做User Login的功能,使用哪个方法可以用最方便的方式去做Query动作?8. 网友们传来的数据总是不安全的!我想要个别处理params[:info](params[:info]内有nickname、email、body三个子参数),请问我可以怎样在存入Database前,过滤各个元素? 9. 请用Iterator来为User Model新增一笔数据吧(字段有:username, password, nickname, email, url)。10. ROR中有一些奇特的约定,尽自己的能力列举你认为ROR中很方便的约定吧?并简要说明怎么用,越多越好。三、应用题目11、对于一个用户输入的Email地址,我该怎么检查它,以最大限度的保证该Email地址的可用性及其真实性呢?给出你的思路和ROR实现的代码段。12、我想要这么一个效果,请问怎么做,我有一个大分类TYPE1,还有个小分类category,如如何实现级联效果,比如我点选第一个下拉框中的一个值,对应更新后面那个和他级联的下拉框中的值。13、我有一个数据表Topic,包含字段有(id,title,body,created_at,owner, category_id),请问你怎么就这个表生成一全量的RSS订阅(比如我想要的订阅地址为:/feed/index)和一个针对每个category的RSS订阅(比如我想要的订阅地址为:/feed/category/rails订阅rails的RSS,rails是分类表中的一个)。14、目前,经理想知道从A地址(例如10.1.3.1)到B地址(例如211.54.2.45)的网络状况,让你尽快的想个办法,可以指定源地址和目标地址,并且可以指定发送包的大小或者需要发送的文件,让你计算出发送完需要多少时间。你该怎么做呢?15、你晓得Trackback(引用)功能么?不知道的话可以上网上搜索下,请简要说明下Trackback的特点和实现原理;你认为目前这种Trackback有什么不足或者缺陷么?如果有,请问有什么办法改良或者完善么?给出你的Trackback实现代码片段(包括。四、拓展题16、你是怎么认识RESTful 的,你认为它的精髓在哪里,谈谈你是怎么认识这个东西的,它可以带给我们什么好处。17、你实际部署过Rails应用么?你会选择什么做为你的服务器;如果你是买的一个虚拟主机空间,你想跑几个Rails应用,该怎么部署呢?谈谈您的部署经验和好的方法以及您的维护经验~
22 May
SuperRedCloth项目就是开发中的RedCloth,也就是RedCloth 4。目标是尽可能地增强RedCloth: 1. 令到RedCloth比原来小2/3 2. 一般情况下将会快10倍以上 3. 消除Textile格式中的二义性安装:$ gem install superredcloth –source http://code.whytheluckystiff.net使用:1.首先在helpers/application_helper.rb 中覆盖textilize方法(这个方法在Rails 1.2中使用的是RedCloth),我们覆盖它,如下:<code> def textilize(text) require_library_or_gem "superredcloth" unless Object.const_defined?(:SuperRedCloth) if text.blank? "" else textilized = SuperRedCloth.new(text) textilized.to_html end end # def textilize</code>2.然后在VIEW可以直接使用,如:<code><%= textilize @page.body %></code>官方主页:http://code.whytheluckystiff.net/redcloth/wiki/SuperRedCloth
22 May
在博客或者其他WEB开发中,有的时候可能想显示一个日历表格,ROR下有个老兄也写了一个helper,功能比较完善,可以按照自己的喜好进行定制,其默认需要的参数是年、月,其他都是定制参数,比如CSS等,代码如参考(http://www.jvoorhis.com/downloads/calendar_helper.rb)使用的时候放在helper里面就可以了。 # Example usage: # calendar(:year => 2005, :month => 6) # This generates the simplest possible 作者主页:http://www.jvoorhis.com/pages/calendar-helper
21 May
It’s not necessary to create a Builder .rxml template to export data as XML. ActiveRecord has a to_xml method that will output the object or result set in XML format. It works with simple objects, to complete tables with includes. Examples:User.find(:all).to_xmlPost.find(:all, :include => [:comments]).to_xmlYAML is also supported, by using to_yaml instead.
21 May
这个需求应该是来自于对一些常量的配置和修改上,比如网站的title等等,如果你想做出一个比较通用的WEB系统,那么这个常量的可修改性就是个不可少的需求!我们的做法是可以放在数据库里面,然后去读取,这个方法显然是可行的,但是我们还可以这么来作,放在一个YAML文件里,把你需要的变量写在这个文件里面,需要注意格式的正确性,然后就可以在程序中引用了,步骤如下:1.在你的/config/environment.rb的上方写上:require ‘yaml’2.在你的/config/environment.rb的下发写上: YOUR_APP_CONFIG = YAML::load(File.open("#{RAILS_ROOT}/config/appconfig.yml"))3.然后你就可以在程序里面进行变量的引用了,如下: YOUR_APP_CONFIG"variable"]如果想改变,只要修改这个文件就OK;如果想增加,则只需要在这个文件里面再增加一个变量就好了。。是不是很方便呀~~
21 May
什么是Trackback呢?简单说来,Trackback是网站与网站之间互相通告的一种方法。它能让甲对乙说:“这篇文章可能是你感兴趣的”,要实现这一动作,甲向乙发送一个 Trackback Ping(引用通告)即可。在这种情况下,一个ping就是一条从一个web服务器发送到另一个服务器的短消息(a small message)。Trackback Ping是由Moveable Type发明的规范,他们说Trackback是:<blockquote>"a framework for peer-to-peer communication and notifications between web sites"。</blockquote>这里是他们的Trackback技术规范文档:http://www.movabletype.org/docs/mttrackback.html举个例子来说明一下。比如B在A的Blog中看了一篇我感兴趣的文章,对这篇文章B自己有一些看法,如果按照传统BBS的做法,B需要在A这篇文章下发表自己的评论,但这样做的话B的文字只能存在于A的网站上,B无法再维护自己的这篇评论。另一个情况是B在自己的Blog中也在写一篇相类似的文章,B希望A也能来看一看B的这篇,传统BBS的习惯还是得到A的文章下发一篇回复,把B的URL贴过去。但有了Trackback Ping,我们的Blog不再需要这样做。Blog 跟BBS有点重要的不同,Blog是一种个人创作,用Blog来发表自己的东西,保存自己的东西,即使是对他人Blog文章的评论也要在自己的Blog中永久保留下来。通过Trackbak,我就可以在自己的Blog中发表文章,同时把自己这篇文章的URL地址Ping到A的那篇文章上去。这样,所有阅读A文章的人也能通过Trackback顺藤摸瓜地来我的Blog看我的文章。所以,当我们的Blog有了Trackback Ping功能,那么谁都可以通过Trackback Ping来发表意见和评论了。这样,多家Blog网站就通过相关话题而联接起来。各种评论在Internet上相互连接而织成一张大网。因此,可以说, Trackback创造出了Blog与BBS、Diary完全不同的文化,Blog的世界通过Trackback而变成真正的无限互连。作为Blogger,让我们习惯于这样讨论问题和做评论吧:把内容写在自己的Blog里面,Trackback Ping到别人的Blog。这个概念是论坛模式里从来没有的,称为Remote Commenting。如何在Blog中实现Trackback?在有Trackback功能的Blog系统中,每篇Blog文章都有两个URL,一个是要访问这篇文章所使用的URL,另一个就是Trackback Ping URL(引用通告地址),它是用来接受来自其他Blog网站Trackback Ping的程序。当我发表文章的时候,想要通知鱼头的话,只需要把鱼头那篇文章的Trackback Ping URL贴到我这边文章中来,我提交文章时,系统就会按照这个URL发送一个Ping给A的那篇文章。而鱼头则将在自己的文章下看到类似这样的一个引用通告:标题: 1ster的文章来自: 1ster的Blog摘要: 1ster的文章内容摘要…地址: http://1ster的文章地址这个Trackback Ping是通过标准的HTTP协议从我的Blog发送到鱼头的Blog的,我的Blog发送一个POST格式的HTTP请求到A那篇文章的 Trackback Ping URL。这个请求的content type是application/x-www-form-URLencoded,它大概是这个样子的:POST http://A文章的TrackbackPingURLContent-Type: application/x-www-form-URLencodedtitle=1ster的文章&url=http://1ster的文章地址&excerpt=1ster的文章摘要&blog_name=1ster的Blog早期版本的Trackback规范中,Ping是GET方式的HTTP请求,现在不再支持GET方式,只能用POST方式。参数包括: * title – 文章的标题 * excerpt – 文章的摘要。在Movable Type系统中,如果摘录信息超过255个字符将会被截断为252个字符,并在后面增加…三个字符 * url – 文章的永久连接。象其它永久连接一样,这个连接应可能准确地在页面中定位文章的入口,因有疑问时这个链接会用到 * blog_name – 发表文章的blog的名称在上述的参数中只有url是必须的。如果title没有提供,url的值将被用作标题。当我的Blog发出这个Trackback Ping后,将接收一个简单的XML格式应答,如果Ping成功,那么应答的格式如下:<blockquote><?xml version="1.0" encoding="iso-8859-1"?><response><error>0</error></response></blockquote>而失败应答的格式为:<blockquote><?xml version="1.0" encoding="iso-8859-1"?><response><error>1</error><message>The error message</message></response></blockquote>
21 May
witter越来越火了,这个提供IM服务的应用,越来越受到大家的关注,越来越多的人加入其中,昨天台湾的一个朋友还说对witter的这个IM功能很感兴趣,想了解是怎么实现的,呵呵~witter通过网络或者SMS(短消息)使得你和自己的朋友取得及时沟通。你有没有考虑过给自己的WebApp加上这样的功能呢,现在借助witter发布的Gem包,可以很方便的实现这个功能了,更多说明请到http://www.rubyinside.com/twitter-gem-twitterize-your-ruby-application-498.html查看,我这里稍微说下用法,如下:# to post an update to twitter$ twitter post "posting from the twitter gem"# to see you and your friends timeline$ twitter timeline命令行接口很简单,支持YAML配置,也支持Ruby的API:twit.update(‘me got dizzy this time’)# Show your friends’ statustwit.timeline(:friends).each do |s| puts s.text, s.user.nameendUse RubyGems as usual to install it:gem install twitter –include-dependenciesps:One note, the gem uses hpricot to parse the xml and there is an annoying bug that reared it’s head in the 0.5+ versions (it doesn’t like xml elements named text). That said, be sure to sudo gem install hpricot –source http://code.whytheluckystiff.net -v 0.4.86 and uninstall any hpricot versions 0.5+.
Comments::最新评论