Rails 起步走

    在这一章中,我们将开始介绍如何建立一个最简单的Hello, World!程式,以及用最快速的方式制作CRUD应用。

    CRUD指的是Create(新增)、Read(读取)、Update(更新)、Delete(删除)四种操作资料的基本方式。

    在上一章安装Rails后,你会在命令列中得到一个的指令,这个指令可以初始一个Rails专案目录。

    首先请打开一个命令列视窗(Terminal),然后找个目录适合放你的Rails专案,就说是projects好了:

    接着,输入以下指令就会建立一个叫做demoRails专案:

    1. $ rails new demo --skip-test-unit

    如果出现建立出来的目录不是demo而是new,表示你的Rails版本是旧版的,请输入rails -v检查Rails的版本必须是3.0以上。不是的话,请回上一章末执行gem install rails安装Rails 4

    你会看到以下讯息显示出总共新增了哪些档案:

    1. create
    2. create README
    3. create Rakefile
    4. create config.ru
    5. create .gitignore
    6. create Gemfile
    7. create app
    8. ...(略)...
    9. create vendor/plugins
    10. create vendor/plugins/.gitkeep

    这样就建立出demo目录,让我们继续,进入刚产生出来的demo目录下:

    1. $ cd demo

    这个目录下包含了一个Rails专案基本会用到的目录结构和档案,让我们简单走访一下,输入ls(Windows读者请输入dir)显示出此目录下的档案:

    启动服务器

    Rails使用了一套叫做Bundler的工具可以帮助我们检查及安装这个Rails应用程式所有依存的套件,在demo目录下输入:

    1. $ bundle install

    可以只输入bundle就是bundle install了。每次有修改Gemfile这个档案,都需要重新执行bundle

    会出现

    1. Fetching source index for http://rubygems.org/
    2. ...
    3. Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

    在开发用的电脑上,我们不需要安装如ApacheIIS的网站服务器。Ruby本身就有提供了HTTP服务器可以执行Rails,要启动它,我们另开启一个指令视窗,cd进到刚刚建立的Rails专案目录然后输入bin/rails server

    1. $ cd projects/demo

    就会出现以下讯息:

    rails server 可以简写为 rails s

    使用Ubuntu作业系统的朋友,如果启动服务器时出现Could not find a JavaScript runtime的错误,请编辑Gemfile这个档案加上一行gem 'therubyracer',输入bundle install安装这个套件,然后再启动一次rails server即可。这是因为在Ubuntu作业系统上默认没有任何JavaScript直译器可以给Rails使用。你可以装Node.js或是安装therubyracer这个Ruby套件来获得JavaScript直译器。

    接着打开你的浏览器前往,我们可以看到Rails的默认首页。这个Welcome Aboard的画面可以确认设定无误,点选About your application’s environment超连结可以看到更多环境资讯。

    要中断服务器的话,请按Ctrl+C(若不灵光请改试Ctrl+Z)。在development开发模式的话,除了修改configvender目录下的档案需要重新启动之外,其他修改通常不需要重新启动,修改的档案会自动重新加载。如果是 production正式上线模式的话,修改任何档案都必须重新启动服务器才会有效果。

    让程式说Hello World!可是我们学写程式的一大传统。我们提过RailsMVC框架,显示Hello World!不需要用到数据库,所以我们只要先写ControllerView,以及让路由指派到这个Controller即可,输入以下指令就会产生出一个叫做welcome的空Controller档案:

    1. $ bin/rails generate controller welcome

    可以简写为bin/rails g controller welcome

    接下来在路由档案config/routes.rb新增一行设定:

    1. Rails.application.routes.draw do
    2. get "welcome/say_hello" => "welcome#say"
    3. # ...
    4. end

    这一行的意思是将http://localhost:3000/welcome/say_hello这样的网址对应到welcome Controllersay Action

    编辑app/controllers/welcome_controller.rb,加入一个say方法:

    1. class WelcomeController < ApplicationController
    2. def say
    3. end
    4. end

    Controller中,一个公开函式(public method)就代表一个Action,一个Action对应一个HTTP的请求和回应。接着我们打开浏览器浏览,你会看到一个错误如下:

    1. Missing template welcome/say, application/say with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in: * "/Users/ihower/projects/demo/app/views"

    这是因为我们还没有准备好View档案。请新增app/views/welcome/say.html.erb这个档案,依照惯例目录名就是Controller名称、档案名是Action名称,第一个附档名说明了这是HTML格式的档案,第二个附档名说明这是ERb样板(我们会在View一章仔细介绍样板)。编辑该档案内容如下:

    1. <h1>Hello, World!</h1>

    这时再重新整理一次浏览器,你就会看到Hello, World!了。

    让我们再新增一个页面并加入超连结。再次编辑路由档案config/routes.rb加入一个路由,变成这样:

    1. Rails.application.routes.draw do
    2. get "welcome/say_hello" => "welcome#say"
    3. get "welcome" => "welcome#index"
    4. # ...
    5. end

    这一行的意思是将http://localhost:3000/welcome这样的网址对应到welcome Controllerindex Action。编辑app/controllers/welcome_controller.rb加入

    新增app/views/welcome/index.html.erb内容是

    1. <p>Hola! It's <%= Time.now %></p>
    2. <p><%= link_to 'Hello!', welcome_say_hello_path %></p>

    TimeRuby内建的时间类别,Time.now会输出目前时间。linkto是_Rails内建的方法可以输出超连结,而welcome_say_hello_path会输出/welcome/sayhello这个网址。这种出现在_View中的辅助方法统称作Helper。浏览,将看到Hola!Hello!超连结。

    如何将网站首页变更为welcome#index呢?编辑config/routes.rb,加上以下的程式码,变成这样:

    1. Rails.application.routes.draw do
    2. get "welcome/say_hello" => "welcome#say"
    3. get "welcome" => "welcome#index"
    4. root :to => "welcome#index"
    5. # ...
    6. end

    这一行的意思是,将网站根目录导引至welcome Controllerindex Action。那在View中要怎么建立回首页的连结呢?编辑app/views/welcome/say.html.erb在Hello, World!下一行加入:

    1. <h1>Hello, World!</h1>
    2. <p><%= link_to "Home", root_path %></p>

    如此一来,网页的首页就会显示Hola!和时间,连到http://localhost:3000/welcome/say_hello的时候也会在底下显示一个「Home」的连结,点下去就会回到首页了。

    设定及建立数据库

    • development 开发模式,用在你的开发的时候
    • test 测试模式,用在执行自动测试时

    设定SQLite数据库

    Rails内建支援这是一套非常轻量的非服务器型数据库程式,它的数据库就只是一个档案而已。流量大的正式上线环境虽然不适合SQLite,不过拿来开发和测试却非常好用。Rails默认也使用SQLite数据库来建立新的专案,以下是默认的设定资料config/database.yml

    1. # SQLite version 3.x
    2. # gem install sqlite3
    3. #
    4. # Ensure the SQLite 3 gem is defined in your Gemfile
    5. # gem 'sqlite3'
    6. default: &default
    7. adapter: sqlite3
    8. pool: 5
    9. timeout: 5000
    10. development:
    11. <<: *default
    12. database: db/development.sqlite3
    13. # Warning: The database defined as "test" will be erased and
    14. # re-generated from your development database when you run "rake".
    15. # Do not set this db to the same as development or production.
    16. test:
    17. <<: *default
    18. database: db/test.sqlite3
    19. production:
    20. <<: *default
    21. database: db/production.sqlite3

    中间那段注解告诉你不要把test数据库设成跟productiondevelopment同一个

    本书接下来也都使用SQLite数据库,因为它完全不需要什么设定就可以使用。

    YAML是一种可读性高,用来表达设定资料的资料格式。它严格要求缩排(建议为两个空白),且冒号后面必须有一个空格。一般我们会预期YAML的值解析出来是字串,因此如果内容是数字或多行文字时,建议加上引号以避免字串解析错误。例如 password: "123456"。如果没有加上引号,这串数字会被解析成Fixnum物件而不是字串String,后续可能造成型别判断错误。

    数据库设定好了,输入以下的指令可以让Rails建立出空的数据库:

    1. $ bin/rake db:create

    这将在db/目录下建立出development.sqlite3这个数据库档案。

    Rake是一种Ruby的命令列工具,你可以输入rake -T列出所有可用的指令。我们会在稍后的章节中详细介绍Rake

    Railsscaffold鹰架功能会自动产生一组ModelViewsController程式码,完成一个简易的CRUD程式以供展示及学习之用。请输入:

    1. $ bin/rails g scaffold person name:string bio:text birthday:date

    产生的档案简单说明如下,请注意Model的名称是用单数person,而ControllerRESTful惯例是用复数people

    db/migrate/20141021135430_create_people.rb用来建立people数据库资料表的Migration(你的档案开头名称会有不同的时间)
    app/models/person.rbperson model档案
    app/controllers/people_controller.rbpeople controller档案
    app/views/people/index.html.erb用来显示所有文章的index页面
    app/views/people/edit.html.erb用来编辑文章的页面
    app/views/people/show.html.erb用来显示特定一篇文章的页面
    app/views/people/new.html.erb用来新增文章的页面
    app/views/people/_form.html.erb用来显示编辑和新增文章的表单局部(Partial)样板
    app/helpers/people_helper.rb可在文章Views中使用的Helper方法
    config/routes.rb设定URL路由规则的档案,scaffold再此新增了一行resources :people
    app/assets/stylesheets/scaffold.scssScaffold鹰架提供的样式档案
    app/assets/stylesheets/people.scsspeople的CSS样式档案
    app/assets/javascripts/people.coffeepeople的JavaScript档案

    虽然鹰架(scaffolding)可以帮助你快速上手,但是可没办法产生出完美符合需求的程式码。因此有经验的Rails程式设计师甚少使用默认的鹰架产生程式码,而是偏好使用Railsgenerator来分别产生ModelController档案,甚至客制出自己专属的scaffold程式。

    scaffold产生出来的程式中,有一项是数据库迁移档(database migration)Migration的用途是建立和修改数据库资料表。Rails使用rake指令来执行MigrationsMigration的档名中包含了Timestamp(时间戳章),用来确保它们可以依照建立时间依序执行。

    请输入以下指令执行Migration

    Rails这时会建立people资料表:

    1. == Createpeople: migrating ====================================================
    2. -- create_table(:people)
    3. == Createpeople: migrated (0.0020s) ===========================================

    因为默认是跑在development模式,这个指令会用config/database.yml设定里的development那段所指定的数据库。

    此时浏览就可以操作了,十分神奇吧!不过,这里就不详细说明其产生出来的程式码了,读者读毕稍后章节后,自会明白。

    Scaffold screenshot

    常见错误

    NoMethodError

    NoMethodError非常明显,就是你打错方法名称了,例如此例中把link_to打成link_too。根据错误讯息你应该可以很容易找到错误是发生在哪个档案、哪一行。

    读取一个不存在、没有初始过的区域变量会出现NameError的错误

    SyntaxError: unexpected $end