Category Archives: 指南

select层叠的AJAX实现

假设我们有两个select,子select的内容需要随父select而动态改变,这篇指南将向你演示如何实现AJAX方式的select层叠: 1. 创建三个资源:country,city,person ruby script/generate scaffold_resource country name:strin ruby script/generate scaffold_resource city country_id:int name:string ruby script/generate scaffold_resource person country_id:int city_id:int name:string 2. 执行rake db:migrate 3. 修改app/views/layouts/people.rhtml,包含prototype: <%= javascript_include_tag ‘prototype’ %> 4. 修改app/views/people/new.rhtml: <p>   <b>Country</b><br />   <%= f.select (:country_id, Country.find_all.collect {|c| [ c.name, c.id ] },     { :include_blank => true },      nchange => remote_function(:update => [...]

Also posted in AJAX | Leave a comment

在Rails中创建多对多映射

AWDwR 有一个小节讲到了如何创建多对多映射,不过使用db:migrate使得这个过程变得更为简单,这是来自thembid.com 的一篇指南,原文在这里 。 为了让例子更容易理解一些,我修改了原文的两个表名,并使用了scaffold_resource替代了model,同时在最后给出了两个截图。这里我使用book和author来作为演示的resource,一本书可以有多个作者,一个作者也可能写了多本书,因此,作者和书属于多对多的关系。 首先,让我们创建resource: ruby script/generate scaffold_resource book title:string ruby script/generate scaffold_resource authors name:string 然后,我们为创建映射关系表: ruby script/generate migration create_authors_books 编辑db/migrate/003_create_authors_books.rb: class CreateAuthorsBooks < ActiveRecord::Migration   def self.up     create_table :authors_books, :id => false do |t|       t.column :author_id, :integer       t.column :book_id, :integer     end     add_index :authors_books, [:author_id, :book_id]     add_index :authors_books, [:book_id]   end   def self.down     remove_index :authors_books, [:book_id] [...]

Also posted in 数据库 | Leave a comment

db:migrate简明指南

AWDwR 有一个小节讲到了如何创建多对多映射,不过使用db:migrate使得这个过程变得更为简单,这是来自thembid.com 的一篇指南,原文在这里 。 为了让例子更容易理解一些,我修改了原文的两个表名,并使用了scaffold_resource替代了model,同时在最后给出了两个截图。这里我使用book和author来作为演示的resource,一本书可以有多个作者,一个作者也可能写了多本书,因此,作者和书属于多对多的关系。 首先,让我们创建resource: ruby script/generate scaffold_resource book title:string ruby script/generate scaffold_resource authors name:string 然后,我们为创建映射关系表: ruby script/generate migration create_authors_books 编辑db/migrate/003_create_authors_books.rb: class CreateAuthorsBooks < ActiveRecord::Migration   def self.up     create_table :authors_books, :id => false do |t|       t.column :author_id, :integer       t.column :book_id, :integer     end     add_index :authors_books, [:author_id, :book_id]     add_index :authors_books, [:book_id]   end   def self.down     remove_index :authors_books, [:book_id] [...]

Also posted in 数据库 | 3 Comments

制作你自己的gem

对于初学者来说,可能经常会使用gem命令来安装一些Ruby软件包,但是随着能力的提升,你可能不再满足于仅仅编写教科书上的示例程序,你开始尝试编写一些有实际用途的程序,并且你觉得这些程序可能会对其它人有用,这时候你就需要将你的程序打包并发布给其他人,Ruby自带的包管理软件gem可以很好的帮你完成这个任务,本篇指南将通过一个简单的“Hello, gem!”程序来演示如何制作自己的GEM程序包。 首先假设我们的程序目录结构如下: gem-sample/   bin/     gem-sample   lib/     gem-sample.rb   spec/     gem-sample-spec.rb   README   CHANGES   Rakefile 我们的sample程序很简单,它只是简单的打印一句话: module GemSample   def GemSample.run     puts “Hello, gem!”   end end 可执行程序实际上也是一个ruby脚本: $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + “/../lib”)) require “gem-sample” GemSample.run 它读取lib文件夹下的gem-smaple.rb文件,然后调用它的run方法。 现在我们要将这个程序打包成一个gem文件,gempackagetask让我们可以通过Rake来完成打包工作,我们可以这样定义我们的Rakefile: require ‘rubygems’ require ‘rake/gempackagetask’ PKG_NAME = “gem-sample” PKG_VERSION = “1.0.0″ PKG_FILE_NAME = “#{PKG_NAME}-#{PKG_VERSION}” PKG_FILES = FileList[   '[A-Z]*’,   ’lib/**/*.rb’,   ’spec/**/*.rb’,   ’bin/**/*’, ] spec = [...]

Posted in 指南 | 1 Comment

如何编写Ruby控制台程序(四)

这是来自O’Reilly Network的一篇关于如何如何使用Ruby及ActiveRecord编写控制台程序的教程,文章通过一个例子程序EarGTD演示了编写控制台程序需要注意的方方面面(文件布局,数据库连接等等),作者是Gregory Brown,你可以在这里找到原文 ,这是第四部分。 输入处理 继续我们的命令行处理,上一节我们通过简单的case语句将命令分派到了不同的处理函数,现在,我们对命令的参数进行处理,在EarGTD中,你可以通过这样形式的命令添加一个任务: $ earGTD + “任务描述 <项目名称> [上下文]” 下面三个函数分别负责从添加命令的参数中获取任务描述,项目名称以及上下文: def parse_project(string)   string =~ /<(.*)>/ && $1.strip end def parse_task(string)   string.gsub(/[<\[].*[>\]]/,”").strip end def parse_context(string)   string =~ /\[(.*)\]/ && $1.strip end 有了上面三个函数,我们要添加一个任务就很简单了: def add_task(description)   task_desc = parse_task(description)   task = Models::Task.create(:description => task_desc)   if (project=parse_project(description))     Models::Project.find_or_create_by_name(project).tasks << task   end   if (context=parse_context(description))     Models::Context.find_or_create_by_name(context).tasks << task [...]

Posted in 指南 | Leave a comment

如何编写Ruby控制台程序(三)

这是来自O’Reilly Network的一篇关于如何如何使用Ruby及ActiveRecord编写控制台程序的教程,文章通过一个例子程序EarGTD演示了编写控制台程序需要注意的方方面面(文件布局,数据库连接等等),作者是Gregory Brown,你可以在这里找到原文 ,这是第二部分。 手动编写Rakefile 在Rails中,你可能经常会用到Rake来完成各种自动化任务(比如单元测试,数据库迁移等),但是你可能并不清楚该如何添加一个新的Rake任务,或 者是从头写一个新的Rakefile,下面就让我们来看看EarGTD是如何通过Rake来实现它的单元测试自动化的,实际上,并不负责: require “rubygems” require “rake” require “rake/testtask” task :default => [:test] Rake::TestTask.new do |test|   test.libs << “test”   test.test_files = Dir[ "test/test_*.rb" ]   test.verbose = true end 这段代码应该不难理解,它新建了一个Test任务来运行所有test目录下的名为test_XXX.rb的文件,并将test任务设为默认任务,也就是你只需要通过简单的rake命令,而不需要指定参数就可以执行test任务了, 使用module来组织你的代码 虽然只是一个简单的控制台程序,但为了易于维护,我们还是应该尽量保持代码的简洁明了,处于对面向对象的景仰,你可能首先想到的是要定义一个类,就像下面这样: module A   def b     puts “this is b”   end end class C   include A end d = C.new d.b #=> [...]

Posted in 指南 | Leave a comment

如何编写Ruby控制台程序(二)

这是来自O’Reilly Network的一篇关于如何如何使用Ruby及ActiveRecord编写控制台程序的教程,文章通过一个例子程序EarGTD演示了编写控制台程序需要注意的方方面面(文件布局,数据库连接等等),作者是Gregory Brown,你可以在这里找到原文 ,这是第二部分。 没有生成器 使用Rails的好处是它可以帮你生成程序的基本框架,你也不需要关心目录结构,但是现在我们打算写一个独立的Ruby程序,因此我们必须自己考虑这些问题了,不过也不用太担心,这不是很复杂。 目录结构 让我们先来看看目录结构吧,EarGTD的目录结构如下: ear_gtd.db test_ear_gtd.db lib/ ear_gtd.rb test/ test_ear_gtd.rb Rakefile earGTD 作为一个示例程序来说,这些文件已经足够了,当然,如果一般的发布版本会有一个bin目录存放可执行脚本,但是为了简单起见,我们先忽略这个。 如果你看过一些Ruby项目的源码,这样的结构在Ruby项目中相当常见,一般lib目录存放你的库文件,data目录存放你的数据文件,test目录存放你的单元测示例。 当然,这个并不是强制的,你也可以将你所有的代码(包括单元测试等等)都放到一个文件中,但是,有些工具可能需要依赖这样的目录结构才能够正常工作。 连接数据库 在Rails中,你可以通过config/database.yml来配置你的数据库连接,但是现在我们需要单独使用ActiveRecord,所以我们还需要做些额外工作。 下面这段代码演示了如何将database.yml文件中的配置信息转换为Ruby代码: development: adapter: sqlite3 database: db/my_database.sqlite3 ActiveRecord::Base.establish_connection(   :adapter => :sqlite3,   :database => “db/my_database.sqlite3″ ) 执行了这段代码后,你就可以通过ActiveRecord来访问你的Model了。 不过,尽管这样也可以工作,但我还是建议你像Rails那样将数据库的连接信息保存到一个YML文件中,事实上,这很简单。 使用YAML库 让我们假设现在你也有一个目录叫做conifg,并且也存放了一个database.yml文件: development: adapter: sqlite3 database: db/my_database.sqlite3 那么现在你可以通过下面这段代码来建立你的数据库连接: require “yaml” ActiveRecord::Base.establish_connection(YAML.load_file(“config/database.yml”)) YAML.load_file会返回一个Hash,因此你可以直接用它作为参数来建立连接。 数据大纲定义 对于我们这个简单的应用来说,没有什么必要使用migration,但是也应该尽量避免直接操作SQL语句,我们可以使用ActiveRecord:Schema来避免直接和SQL打交道。 EarGTD的数据库相当简单: ActiveRecord::Schema.define do   create_table [...]

Posted in 指南 | Leave a comment

如何编写Ruby控制台程序(一)

这是来自O’Reilly Network的一篇关于如何如何使用Ruby及ActiveRecord编写控制台程序的教程,文章通过一个例子程序EarGTD演示了编写控制台程序需要注意的方方面面(文件布局,数据库连接等等),作者是Gregory Brown,你可以在这里找到原文 。 抛弃Rails 如果你一开始就是通过Rails来学习Ruby,那么你很可能会发现,你需要学习的东西实在是太多了,这是因为Rails虽然只是一个框架,但它和Ruby的结合非常紧密,因此,你有可能会搞不清楚,到底那些东西是属于Ruby,而那些又属于Rails。 这在某种程度上是好事情,因为这降低了你的学习曲线,你在学习Rails的同时也学到了Ruby。但是如果你认为你的任务并不适合用浏览器来表现,也不适合MVC架构,那么你可能想抛弃Rails,试试纯Ruby编程,事实上,这并不复杂。 抛开Rails单独使用Ruby的另外一个理由就是,这并不意外着你与Rails老死不相往来,事实上,由于Rails框架本身就是由许多模块组装而成的,因此你可以在你的Ruby程序中单独使用Rails的任何一个组件(比如ActiveRecord)。 在这篇指南中,我们将通过一个例子程序EarGTD(可以在这里下载源码,但需要sqlite支持)来演示如果构建一个基于Ruby和ActiveRecord的控制台程序,下面让我们先来看看EarGTD能为我们做些什么? EarGTD 我相信许多程序员都很喜欢David Allen’s的Getting Things Done (GTD)方法(至少应该听过吧,如果没听过,建议先看看这个链接指向的wikipedia页面,现在解封了),我一般将它看作是一个“巨大的ToDo列 表”,GTD的好处在于所有的任务都可以在某个点得到收敛,因此你可以很简单的计算出在某个时间点上有那些因素在影响你的进度。 EarGTD实现了GTD方法的一个最小集合,它允许你通过两种方式来组织你的任务:项目或者是上下文。 项目由一组相互关联的任务组成,任务的范围相当宽泛,它可以是编码相关的任务,也可以是类似“清理垃圾桶”这样的任务。 上下文则是一组过滤器,它可以让你迅速的决定在某个时间可以做哪些事情,有些事情不需要这样的过滤器,但有些则是必需的,比如如果你想要”修理草坪“(任务),那么你必须首先在“家里”(上下文)才行。 GTD是一个很庞大的话题,但是鉴于我们这篇文章讲述的是Ruby编程,因此我不想太深入这个话题,如果你感兴趣的话,可以自己找资料深入了解。 EarGTD实现了一个非常简单的命令行界面,可以让你通过项目或者是上下文的方式来管理任务,但也仅限于此,因为我们只是想通过它来演示如果构造一个纯Ruby的控制台程序。 下面让我们先通过几个例子来了解一下它是如何工作的吧: $ earGTD @ Looks like you have nothing to do. $ earGTD + “递交计费模块代码 <网不通> [工作]” $ earGTD + “支持银行卡缴费 <网不通> [工作]” $ earGTD + “打电话给老张 [工作]” $ earGTD + “洗衣服 <清洁> [家里]” [...]

Posted in 指南 | Leave a comment

RSpec简明指南

这是David Chelimsky写的一篇RSpec简明指南,原文在这里。 简介 要了解RSpec,我们首先需要了解什么是行为驱动开发(Behaviour Driven Development,简称BDD),BDD是一种融合了可接受性测试驱动计划(Acceptance Test Driven Planning),域驱动设计(Domain Driven Design)以及测试驱动开发(Test Driven Development,简称TDD)的敏捷开发模型。RSpec为BDD开发提供TDD支持。 你可以简单的将RSpec看作一个传统的单元测试框架,但我们更愿意将它看成是一种领域特定语言(Domain Specific Language,以下简称DSL),它的主要作用就是描述我们对系统执行某个样例(example)的期望行为(behavior)。 这篇指南遵从TDD思想,但是我们将使用行为(behavior)和样例(example)来代替测试例(test case)和测试方法(test method),想知道我们为什么采用这样的术语,请参看Dan North, Dave Astels, 以及 Brian Marick 的相关文章。 安装 目前RSpec的最新版本是1.0.5,需要Ruby184以上版本,可以通过下面这条命令安装: # gem install rspec 准备工作 整篇指南都围绕一个例子展开,因此在开始前,你最好先为这个例子建个目录: $ mkdir rspec_tutorial $ cd rspec_tutorial 开始 我们首先要了解的是RSpec DSL的”describe”与”it”方法,这两个方法有很多其它的名字(但是我们不推荐使用它们),我们之所以使用这样的命名,只是想让你站在行为(behavior)而不是结构(structure)的角度进行思考。 创建名为user_spec.rb的文件: describe User do end describe方法创建一个Behavior实例,所以你可以将”describe User”理解为”描述用户的行为(describe the behaviour of the User [...]

Also posted in 测试 | 5 Comments

Rails Rake指南

这是Rails Envy网站的一篇Rake指南,你可以在这里找到原文。 作为RoR开发者,你对Rake一定不会陌生,你可能用它来完成你的单元测试,也可能是迁移数据库,但是你真正理解这些Rake任务到底是怎么运作的吗?你有尝试过创建你自己的Rake任务吗? 在这篇文章中,我们将会介绍Rake的由来,以及如何在Rails中使用它,通过这篇文章的学习,你将掌握如何使用Rake创建你自己的任务。 为什么要有Rake 要理解Rake,我们首先得来了解一下Rake的历史悠远的祖先:Make。因此我们需要暂且回到解释型语言产生之前的久远年代,在那个时代,所有代码都需 要被编译,然后才能够被执行,所以当你从Internet下载到一个相当庞大的程序后,一般来说,除了源代码,程序包中还会包含一个类似 “install_me.sh”的Shell脚本,它会负责帮你完成源代码的编译,并生成最终的可执行文件。 这看起来很完美,不是吗?对用户来说可能如此,但对于开发者来说,这却是个相当粗笨的方法,因为即使你只是修改了一个文件中的一小段代码,”install_me.sh”也必须将所有的源代码都重新编译一遍,才能生成最终的可执行文件。 因此,针对这个问题,Bell实验室的Stuart Feldman创造了Make: Make可以识别自上次编译之后那些文件发生了改变,从而在下次编译时只对这些发生改变的文件进行编译,而忽略那些没有变化的文件,从而大大降低了程序的编译时间。 Make同时支持依赖关系追踪,也就是你可以告诉编译器,文件A依赖于文件B,因此当文件B发生改变后,文件A也会被重新编译,并且如果编译文件A时,文件B还没有被编译,那么Make会告诉编译器应该先编译文件B。 Make 实际上是一个跟ls和dir差不多的可执行文件,只不过你需要提供一个Makefile文件给它作为输入,Makefile中对每个需要编译的文件及它们 的依赖关系进行定义,Makefile的语法类似于Shell脚本,但又有些不同,这里我们不需要关心Makefile的语法。 随着Make的语言中立性,任何语言的程序都可以使用它来作为构建(build)系统,事实上,在Rake产生之前,许多Ruby项目也是采用Make作为构建系统的。 你可能会奇怪:“Ruby程序并不需要被编译,为何还要使用Make呢?”,是的,Ruby的确不需要编译,事实上,Ruby程序员使用Make是出于以下两个原因: 创 建任务,对于大型程序来说,编译完成并不意味着可以了事,往往你需要编写一大堆的脚本来控制它的运行,或者查看它的运行状态等等,这种情况下,你就可以创 建一个Makefile来管理所有这些任务,然后你就可以使用诸如“make stupid”,“make clever”来分别运行糊涂和聪明任务了。 依 赖关系追踪,当你开始写一个库的时候,你可能会发现,越来越的的任务存在重复,比如”migrate“和”shema: dump“就都需要连接数据库,这时你就可以抽象出一个”connect_to_db”任务,并设置”migrate”和”shema: dump”任务都依赖于”connect_to_db”,这样当你单独运行”migrate”或者”shema:dump”任务时, “connect_to_db”任务都会被首先调用,如果你同时运行这两个任务,那么”connect_to_db”任务只会被执行一次。 Rake是怎么来的? 很多年以前,当 Jim Weirich还在为一个Java项目工作时,他最初的选择也是Makefile,但是很快他意识到:要是能够在Makefile中嵌入Ruby代码,那会是多么的方便呀,于是,Rake就这么产生了。 Rake支持任务创建,任务依赖关系追踪,以及文件编译时间识别。最后一个功能对Ruby程序员应该用不到,但如果你同时还是一个C程序员,那么你可以尝试使用Rake来替代Make。 Rake如何工作 让我们通过一个例子来说明吧,假设我今天很郁闷,想要借酒消愁,这个过程涉及以下几个任务: 买酒 买下酒菜 搞掂它们 假设使用Rake来管理这3个任务,那么我首先需要创建一个Rakefile文件: task :purchaseAlcohol do   puts “来瓶五粮液” end task :mixDrink do   puts “上盘花生米” end task :getSmashed do   puts [...]

Posted in 指南 | 1 Comment