![]() |
||
本教程介绍如何使用 Oracle 安装 Ruby/Rails,以及如何开发高效且功能强大的 Ruby/Rails 应用程序。您将获得为企业创建强大的 Ruby/Rails 应用程序所需的知识。
大约 1 个小时
Ruby on Rails 是一个免费的 Web 应用程序框架,旨在使我们能够更加快捷地创建数据库驱动的 Web 站点,并从一开始就提供主要代码框架(结构)。Ruby on Rails 通常缩写为 Rails 或 RoR,它是一个用 Ruby 编程语言编写的开源项目,使用 Rails 框架的应用程序是用模型-视图-控制器设计模式开发的。
RoR 在 J2EE 和 PHP 编程人员中备受推崇。当您了解 RoR 的优势后,它对 J2EE 和 PHP 编程人员的吸引力具有重要作用。首先,它使用任何自视甚高的设计模式都很钦佩的严格的模型-视图-控制器体系结构 — 这可以解释它为什么吸引了大量 J2EE 开发人员。其次,使用 Rails 可以轻松地构建基本系统 — 这对 PHP 开发人员具有吸引力。
RoR 为 MVC 提供了令人满意的解决方案。模型不仅仅是数据;它执行适用于该数据的所有业务规则。模型既可充当网关守卫又可充当数据存储。视图通常基于模型中的数据生成一个用户界面。尽管视图可能会通过各种方式向用户显示输入的数据,但视图本身从不处理传入的数据。数据显示之后,视图的工作就完成了。控制器接收来自外界的事件(通常是用户输入),与模型进行交互,并向用户显示相应的视图。
RoR 将 ActiveRecord 作为对象关系映射 (ORM) 层提供,以便连接数据库和操作数据。ActiveRecord 严格遵循标准的 ORM 模型:表映射到类,行映射到对象,列映射到对象属性。
创建 Rails 应用程序时,将在根目录下生成以下目录和文件:app、components、config、db、doc、lib、log、public、Rakefile、README、script、test、tmp 和 vendor。
Ruby 是一种动态的开源编程语言,重点关注简单性和工作效率。其简洁的语法易于阅读、便于编写。要了解有关 Ruby 语言的更多信息,参见附录:Ruby 入门。
要获得更多信息,您可以访问 Ruby on Rails OTN 论坛。
您将在本节中使用以下命令:
OCI8.new (userid, password, dbname = nil, privilege = nil): |
通过 userid 和 password 连接到 Oracle。dbname 是 Net8 的连接字符串。如果您需要 DBA 权限,则将 privilege 设置为 :SYSDBA 或 :SYSOPER。
|
|
OCI8#logoff |
断开与 Oracle 的连接。将回滚未提交的事务。 |
|
OCIError | 包含 Oracle 的错误代码的异常类。您可以通过 OCIError#message 获得错误消息,通过 OCIError#code 获得错误代码。 |
创建 ruby 脚本过程中的第一个任务是创建到数据库的连接。执行以下步骤:
. |
在终端窗口中,通过执行以下命令来执行 connect.rb 脚本: export NLS_LANG=American_America.UTF8 ruby connect.rb 如果连接成功,您会看到上面的消息;如果连接失败,您将看到一条错误消息。 connect.rb 文件的内容如下: # connect.rb: Create connections to Oracle
|
---|---|
. |
本教程的其余脚本中将包括以下命令: require 'config.rb'
|
您将在本节中使用以下命令:
OCI8#parse (sql) |
创建一个游标,准备执行 SQL 语句并返回 OCI8::Cursor 的实例。 |
|
OCI8#exec (sql, *bindvars) |
执行 SQL 语句。返回值的类型取决于 SQL 语句的类型。指定 bindvars 后,它们在执行前作为绑定变量进行绑定。 |
|
OCI8::Cursor#exec(*bindvars) | 执行用游标分配的 SQL 语句。返回值的类型取决于 SQL 语句的类型。 | |
OCI8::Cursor#getColNames | 将选择列表的名称作为数组获取。在执行后使用此方法。 |
要创建一个简单查询并显示结果,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 fetch.rb 脚本: ruby fetch.rb 其输出显示在屏幕截图中。 fetch.rb 文件的内容如下: #fetch.rb: Fetch data from database
|
---|---|
. |
还可以通过另一种方式编写更针对于 ruby 的相同的代码。在终端窗口中,通过执行以下命令来执行 fetch_r.rb 脚本: ruby fetch_r.rb The output is shown in the screenshot.
fetch_r.rb 文件的内容如下: # fetch_r.rb: Fetch in a more ruby-like way
|
. |
在获取许多行时,预先获取有助于改善性能。在终端窗口中,通过执行以下命令来执行 prefetch.rb 脚本: ruby prefetch.rb The output is shown in the screenshot.
prefetch.rb 文件的内容如下: # prefetch.rb: Prefetch data
|
绑定变量提高了代码可重用性,消除了 SQL 注入攻击的风险。您将在本节中使用以下命令:
OCI8::Cursor#bind_param(key, val, type = nil, length = nil) |
显式绑定变量。当 key 为数字时,它通过位置绑定(从 1 开始)。当 key 为字符串时,它通过占位符名称绑定。 |
|
OCI8#exec (sql, *bindvars) or OCI8::Cursor#exec(*bindvars) |
也可以通过 bindvars 绑定变量。 |
|
OCI8::Cursor#[key] | 获取/设置绑定变量的值。 |
要在本示例中使用绑定变量,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 bind.rb 脚本: ruby bind.rb 其输出显示在屏幕截图中。 bind.rb 文件的内容如下: # bind.rb: How to bind variables
|
---|---|
. |
要使用绑定变量测试性能改善,通过执行以下命令来执行 bind_perf_test.rb 脚本: ruby bind_perf_test.rb The output is shown in the screenshot.
bind_perf_test.rb 文件的内容如下: # bind_perf_test.rb: Performance test for binding variables
|
您将在本节中使用以下命令:
OCI8::Cursor#define(pos, type, length = nil) |
在分析和执行过程中使用该方法。pos 从 1 开始。当 type 为 String 时使用 length。 |
您可以显式指明获取的值的数据类型。要在本示例中定义数据类型,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 define.rb 脚本: ruby define.rb 其输出显示在屏幕截图中。 您会看到两个输出块之间的差别。 define.rb 文件的内容如下: # define.rb: Define output columns require 'config.rb' # Create a connection to Oracle conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER) # Prepare the data conn.exec("DELETE FROM test_define"); conn.exec("INSERT INTO test_define VALUES(1,'Scott Tiger', SYSDATE, SYSTIMESTAMP)") # Define to fetch Date and Time cursor = conn.parse("SELECT name,birthdate,lastvisit FROM test_define WHERE id = :id") cursor.bind_param(1, 1) cursor.define(1, String, 100) cursor.define(2, Date) cursor.define(3, Time) cursor.exec while r = cursor.fetch puts r.join("\n") end puts # Define to fetch Date and Time as String #conn.exec("ALTER SESSION SET nls_territory='TAIWAN' nls_language='TRADITIONAL CHINESE'") cursor = conn.parse("SELECT name,birthdate,lastvisit FROM test_define WHERE id = :id") cursor.bind_param(1, 1) cursor.define(1, String, 100) cursor.define(2, String, 100) cursor.define(3, String, 100) cursor.exec while r = cursor.fetch puts r.join("\n") end conn.logoff puts '-'*80
|
---|
在 Oracle 数据库中操作数据(插入、更新或删除数据)时,更改的数据或新数据在提交到数据库中之前仅在数据库会话中可用。更改的数据提交至数据库,然后可供其他用户和会话使用。这是一个数据库事务。
单独提交每个更改会额外增加服务器的负载。通常,您希望提交所有数据或者什么都不提交。进行您自己的事务控制具有性能和数据完整性优势。
您将在本节中使用以下命令:
OCI8#autocommit |
获取/设置自动提交模式的状态。默认值是 false(记住:注销时不回滚未提交的事务)。如果为 true,每次执行 insert/update/delete 语句时都自动提交事务。 |
|
OCI8#commit() | 提交事务。 | |
OCI8#rollback() | 回滚事务。 |
要了解如何管理事务,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 transaction.rb 脚本: ruby transaction.rb 该脚本使用 conn1 连接更新一行。在 Oracle 中,新数据在提交前仅在原始数据库会话中可见。其输出显示在屏幕截图中。 在这种情况下,conn2 连接不知道 conn1 的未提交事务发生了什么。 transaction.rb 文件的内容如下: # transaction.rb: How to use transactions
|
---|---|
. |
更新 transaction.rb 脚本,取消对 conn1.autocommit = true 的注释,然后保存文件。 使用以下命令再次执行脚本: ruby transaction.rb 现在,conn2 知道哪些内容是新增的。其输出显示在屏幕截图中。
|
. |
单独提交每一行会额外增加服务器的负载。您可以比较单独提交每行与在事务结束后提交之间的性能差异。要测试差别,使用以下命令执行 trans_perf_test.rb 脚本: ruby trans_perf_test.rb 注意,第二个数字比第一个数字小。其输出显示在屏幕截图中。 trans_perf_test.rb 文件的内容如下: # trans_perf_test.rb: Performance test for transactions
|
PL/SQL 是 Oracle 对 SQL 的过程语言扩展。PL/SQL 存储过程和函数存储在数据库中,因此其访问速度非常快。使用 PL/SQL 存储过程允许所有数据库应用程序重用逻辑,无论应用程序以何种方式访问数据库。许多与数据相关的操作在 PL/SQL 中的执行速度比将数据提取到一个程序中(例如,Ruby)然后再进行处理的速度快。
您将在本节中使用以下命令:
DBMS_UTILITY 和 DBMS_OUTPUT |
Oracle 存储程序包。TO_CHAR 是一个内置函数。 |
要在 Ruby 脚本中调用 PL/SQL 过程和函数,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 plsql.rb 脚本: ruby plsql.rb 其输出显示在屏幕截图中。 plsql.rb 文件的内容如下: # plsql.rb: Call PL/SQL procedures and functions
|
---|
Oracle 字符大对象 (CLOB) 和二进制大对象 (BLOB) 列(以及 PL/SQL 变量)可以包含大容量 (GB) 的字符和二进制数据。您将在本节中使用以下命令:
OCI8::BLOB#available |
检查 BLOB 是否可用。要使用 BLOB,您首先需要插入 EMPTY_BLOB()。 |
|
OCI8::BLOB#read(size = nil) | 从 BLOB 读取最大的字节大小,如果大小省略,则读取到文件结束处。 | |
OCI8::BLOB#write(string) | 将给定的字符串写入到 BLOB。 |
要创建一个小型应用程序以将图像加载并显示到数据库,执行以下步骤。
. |
脚本文件所在的文件夹中有一个 PNG 文件。创建一个名为 download 的文件夹。在终端窗口中,通过执行以下命令来执行 blob.rb 脚本: mkdir download 其输出显示在屏幕截图中。 blob.rb 文件的内容如下: #blob.rb: Save and Load BLOB
|
---|---|
. |
查看 ruby.png 文件的权限。执行以下命令: ls -l ruby.png download/ruby.png
|
所有版本的 Oracle 数据库都包含“XML DB”。此试验包括将 XML 数据从 Oracle 返回至 Ruby 的基本操作。您将在本节中使用以下命令:
DBMS_XMLGEN.getxml (statement) |
根据 SELECT 语句从关系数据生成 XML。它返回 CLOB。 |
要了解 Oracle 的基本 XML 功能,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 xml.rb 脚本: ruby xml.rb 其输出显示在屏幕截图中。 xml.rb 文件的内容如下: # xml.rb: Generate a xml document based on relational data
|
---|
ActiveRecord 连接业务对象和数据库表以创建持久的域模型,其中的逻辑和数据位于一个包装中。它是对象关系映射 (ORM) 设计模式的一个实现。要在本示例中使用 ActiveRecord,执行以下步骤。
. |
在终端窗口中,通过执行以下命令来执行 activerecord.rb 脚本: ruby activerecord.rb 其输出显示在屏幕截图中。 activerecord.rb 文件的内容如下: # activerecord.rb: Using ActiveRecord, the ORM module
|
---|
在本教程的其余部分,您将使用以下术语:
Rake | 一个用于构建其他 Ruby 程序的 Ruby 程序。在 Rails 中,Rake 用于执行一系列任务,如 db:migrate、db:schema:dump、db:schema:load、db:test:prepare 和 db:test:purge。它在作用域和目的方面与常见的 Linux 设计工具类似。 |
模型 | 一个 Ruby 类,代表您应用程序中的一个重要对象,通过 ActiveRecord 的 ORM 链接到您的数据库表。 |
迁移 | 开发人员可以在 Ruby(而非数据描述语言 (DDL))中创建、修改和删除其数据库对象。 |
结构 | 通过创建、编辑、查看和删除 ActiveRecord 类反映的条目,为您的数据提供一个简单接口。结构生成后,它将包含控制器文件(确定您应用程序的用户最终转向哪些页面)和视图文件(呈现应用程序用户将看到的页面)。 |
要使用迁移和结构构建一个 Rails 应用程序,执行以下步骤。
. |
您将创建一个名为 holapp 的非常基本的 Rails 应用程序。在终端窗口中执行以下命令: rails holapp
|
---|---|
. |
用以下内容替换 config/database.yml 文件中的 development 部分,然后保存并关闭该文件。 development:
|
. |
现在可以生成 comic 模型。在终端窗口中执行以下命令: ruby script/generate model comic
|
. |
您想编辑生成的脚本。在终端窗口中输入以下命令: gedit db/migrate/*_create_comics.rb
|
. |
用以下内容替换 self.up 部分,然后保存并关闭该文件。 def self.up
|
. |
现在可以对数据库迁移进行 rake 操作,以生成目标表。在终端窗口中输入以下命令: rake db:migrate
|
. |
可以通过以下命令生成 comic 模型的结构 ruby script/generate scaffold --skip-migration comic name:string description:string price:float
|
. |
Webrick 是用 Ruby 编写的 HTTP 服务器库,它使用 servlet 扩展其功能。使用以下命令启动 Webrick 服务器: ruby script/server
|
. |
您可以查看该应用程序。打开一个浏览器窗口,输入以下 URL。单击 New Comic 创建一条记录,以确保该应用程序正常运行。 http://localhost:3000/comics 输入 comic 信息,然后单击 Create。 comic 创建成功。单击 Back。
|
. |
创建另一个 comic。选择 New comic。 输入 comic 信息,然后单击 Create。 另一个 comic 创建成功。单击 Back。
|
. |
列出了这两个 comic。您还可以对第一个 comic 选择 Edit 进行编辑。 更改任何信息后单击 Update。 更新了该 comic。单击 Back。
|
. |
还可删除一个 comic。对其中一个 comic 选择 Destroy。 单击 OK 确认。 更新了该 comic。单击 Back。
|
. |
停止脚本服务器。在运行该服务器的窗口中按 Control+c。
|
教程这一节将有助于您了解如何在 Rails 中建立各种数据关系的模型并基于这些关系构建应用程序。为此,您将创建一个应用程序,该程序维护一个 articles 和 authors 数据库。
首先您将创建一个应用程序,以便通过该程序输入作者和文章。此外,您还将更改表单以便输入某篇文章时可显示含有作者的弹出列表并在 Listing 和 Show 页面中显示文章作者。该应用程序当前在表间是一对一的关系。执行以下步骤:
. |
另外打开一个终端窗口,执行以下命令: cd /home/rubyhol/holapp
|
---|---|
. |
生成 author 模型的结构。在终端窗口中执行以下命令: ruby script/generate scaffold author name:string vocation:string
|
. |
生成 article 模型的结构。在终端窗口中执行以下命令: ruby script/generate scaffold article title:string author_id:integer abstract:text
|
. |
现在,您需要让 Rails 知道 Article 模型和 Author 模型之间的关系。为此,需要对生成的模型脚本进行编辑。在终端窗口中输入以下命令: gedit app/models/author.rb
|
. |
用以下内容替换文件的内容,然后保存并关闭该文件。 class Author < ActiveRecord::Base
|
. |
您想编辑生成的脚本。在终端窗口中输入以下命令: gedit app/models/article.rb
|
. |
用以下内容替换文件的内容,然后保存并关闭该文件。 class Article < ActiveRecord::Base
|
. |
现在可以对数据库迁移进行 rake 操作,以生成目标表。在终端窗口中输入以下命令: rake db:migrate
|
. |
在终端窗口中,通过执行以下命令再次启动脚本服务器: script/server &
|
. |
您可以查看该应用程序。打开浏览器窗口,输入以下 URL,然后选择 New author。 http://localhost:3000/authors 输入一位新作者,然后单击 Create。 该作者创建成功。单击 Back。
|
. |
您想再创建一位作者。选择 New author。 输入一位新作者,然后单击 Create。 该作者创建成功。单击 Back。 随即显示您添加的作者列表。
|
. |
现在您想创建一些文章。输入以下 URL,然后选择 New articles。 http://localhost:3000/articles 在 Title 处输入一个标题,对 Author 指定 Julia Child,输入任何摘要信息。然后单击 Create。 该文章创建成功。 请注意,这里的 Author 为 0。这是因为 author_id 的值无效,结果是“Julia Child”变成了 0。在下一节中,您将改进 new 和 edit 表单,以便能够通过一个弹出列表按姓名选择作者(该弹出列表显示姓名但在代码中返回 author_id)。
|
您将对生成的表单进行改进,从而在创建文章时对 Author 域生成一个弹出列表。另外,您还将修改 listings 和 show 页面以便这些页面能正确显示作者。执行以下步骤:
. |
在新的终端窗口中输入以下命令(因为您之前的窗口正在运行脚本/服务器)。 cd holapp gedit app/views/articles/new.html.erb 将下面这行: <%= f.text_field :author_id %> 替换为 <%= f.collection_select(:author_id, Author.all, :id, :name) %>
该文件现在应如下所示。
|
---|---|
. |
对 articles 目录中的 edit.html.erb 文件执行相同的操作。在终端窗口中输入以下命令: gedit app/views/articles/edit.html.erb
|
. |
将下面这行: <%= f.text_field :author_id %> 替换为 <%= f.collection_select(:author_id, Author.all, :id, :name) %>
该文件现在应如下所示。
|
. |
再次输入以下 URL。您会看到您在前面创建的文章出现在该列表中。选择 Edit。 http://localhost:3000/articles 注意,现在您可从一个选择列表中选择作者了。选择 Julia Child。然后单击 Update。 该文章创建成功。 注意这里的 Author: 1。此为 author_id 的值。您可将此值改为姓名。
|
. |
下面将更改 articles 目录中的 index.html.erb 文件。在终端窗口中输入以下命令: gedit app/views/articles/index.html.erb
|
. |
将下面这行: <td><%=h article.author_id %></td> 替换为 <td><%=h article.author.name %></td>
该文件现在应如下所示。
|
. |
对 articles 目录中的 edit.html.erb 文件执行相同的操作。在终端窗口中输入以下命令: gedit app/views/articles/show.html.erb
|
. |
将下面这行: <%=h article.author_id %> 替换为 <%=h article.author.name %>
该文件现在应如下所示。
|
. |
再次输入以下 URL。您会看到此时该作者出现在列表中。选择 Show。 http://localhost:3000/articles 您现在可在 Show 模式下看到所有信息。
|
您希望允许一位作者撰写多篇文章。这需要将 Authors 表和 Articles 表之间的关系改为一对多的关系。执行以下步骤:
. |
为了指明这种关系,需要更改 author.rb 文件。在终端窗口中输入以下命令: gedit app/models/author.rb
|
---|---|
. |
将下面这行: has_one : article 替换为 has_many : articles
|
. |
再次输入以下 URL,然后选择 New article。 http://localhost:3000/articles 新建一个文章。对 Author 选择 Julia Child,然后单击 Create。 该文章创建成功。单击 Back。 两个文章同时显示出来。
|
您希望允许多位作者合撰一篇文章。这需要将 Authors 表和 Articles 表之间的关系改为多对多的关系。执行以下步骤:
. |
您需要在 authors.rb 文件中再次更改该关系。在终端窗口中输入以下命令: gedit app/models/author.rb
|
---|---|
. |
将下面这行: has_many :articles 替换为 has_and_belongs_to_many :articles
|
. |
另外还需要更改 article.rb 文件。在终端窗口中输入以下命令: gedit app/models/article.rb
|
. |
将下面这行: belongs_to :author 替换为 has_and_belongs_to_many :authors
|
. |
现在需要创建 Authors 和 Articles 之间的一个联接表。在终端窗口中输入以下命令: script/generate migration CreateArticlesAuthors
|
. |
现在需要对刚创建的文件进行更改以创建一个表来存储作者和文章。在终端窗口中输入以下命令: gedit db/migrate/*_create_articles_authors.rb
|
. |
将下面的内容: def self.up end def self.down end 替换为 def self.up create_table :articles_authors, :id => false do |t| t.integer :author_id t.integer :article_id t.timestamps end end def self.down drop_table :articles_authors end
|
. |
现在可以对数据库迁移进行 rake 操作,以生成目标表。在终端窗口中输入以下命令: rake db:migrate
|
. |
再次输入以下 URL。注意此时出现了一个错误。 http://localhost:3000/articles
|
. |
既然现在是多对多的关系,Article 模型就具有名为 authors 和 author_ids 的方法而不是名为 author 和 author_id 的方法。要纠正这个错误,需要在 new.html.erb 文件中创建和编辑弹出列表并显示您前面创建的用于处理多位作者的域。在终端窗口中输入以下命令: gedit app/views/articles/new.html.erb
|
. |
将下面这行: <%= f.collection_select(:author_id, Author.all, :id, :name) %> 替换为 <%= f.collection_select(:author_ids, Author.all, :id, :name, {},
{:multiple => :multiple} ) %>
该文件现在应如下所示。
|
. |
另外还需要更改 articles 目录中的 edit.html.erb 文件。在终端窗口中输入以下命令: gedit app/views/articles/edit.html.erb
|
. |
将下面这行: <%= f.collection_select(:author_id, Author.all, :id, :name) %> 替换为 <%= f.collection_select(:author_ids, Author.all, :id, :name, {},
{:multiple => :multiple} ) %>
该文件现在应如下所示。
|
. |
还需要更改 articles 目录中的 index.html.erb 文件。在终端窗口中输入以下命令: gedit app/views/articles/index.html.erb
|
. |
将下面这行: <th>Author</th> 替换为 <th>Authors</th>
需要获取所有作者的姓名并执行 join 操作将它们连接在一起。将下面这行: <td><%=h article.author.name %></td>
替换为 <td><%=h article.authors.map {|auth| auth.name}.join(", ") %></td>
该文件现在应如下所示。
|
. |
最后,更改 articles 目录中的 show.html.erb 文件。在终端窗口中输入以下命令: gedit app/views/articles/show.html.erb
|
. |
将以下代码行: <b>Author: </b> <%=h article.author.name %> 替换为 <b>Authors: </b>
<%=h article.authors.map {|auth| auth.name}.join(", ") %>
该文件现在应如下所示。
|
. |
再次输入以下 URL。注意列表中没有显示任何作者。这是因为您切换了表达式。您可能已纠正了这个问题,即已使用一个迁移将 articles 表中的数据引入到了 articles_authors 表中。但这里我们使用应用程序将作者添加回来。选择 Boning a Duck 标题的 Edit 链接。 http://localhost:3000/articles 对 Author 选择 Julia Child,然后单击 Update。注意这里的选择列表允许您选择多位作者而不是只选一位。 该文章更新成功。单击 Back。 选择 The Importance of Butter 标题的 Edit 链接。 按下 Control 键的同时选择这两位作者,单击 Update。 该文章更新成功。单击 Back。 现在该文章显示不止一位作者。
|
使用 AJAX 是为了让浏览器端更智能,使其表现得几乎就像“常规的”应用程序。您的页面可以是交互式的,并且可从服务器获取更新而不必刷新整个窗口。
例如,您可能会有一些文章,它们在开始时是正在进行的工作,随后您完成了它们。您希望总是能够看到未完成文章的列表。将一篇文章标记为已完成后,您希望更新该列表而不必刷新整个页面。
但在使用 AJAX 之前,开始时使用一个非 AJAX 的“unfinished”列表是最容易的。您需要更新数据库表以明确一篇文章是否已完成。文章开始时是未完成状态,将可以使用一个按钮来将它们标记为已完成。为了便于访问,您的页面布局中将有一个列表来显示所有未完成的文章。执行以下步骤:
. |
添加一个 boolean 类型的列 is_finished。在终端窗口中执行以下命令: script/generate migration AddIsFinishedToArticle is_finished:boolean
|
---|---|
. |
接着,需要将现有文章标记为未完成。在终端窗口中执行以下命令: gedit db/migrate/*_add_is_finished_to_article.rb
|
. |
将以下行: add_column :articles, :is_finished, :boolean 更改为 add_column :articles, :is_finished, :boolean, :default => false Article.reset_column_information Article.find(:all).each do |a| a.is_finished = false end
|
. |
现在您将更新数据库。在终端窗口中输入以下命令: rake db:migrate
|
. |
接着,您想添加一个“Mark Finished”按钮,使其调用新的 mark_finished 操作。在终端窗口中输入以下命令: gedit app/views/articles/show.html.erb
|
. |
在 <%= link_to 'Back', articles_path %> 行的后面添加下面一行。 <%= button_to "Mark Finished", :action => :mark_finished, :id => @article.id %>
|
. |
您需要更新页面布局以显示到未完成文章的链接。应使此代码与主布局分离开来。您将生成一个新的“局部模板”,其文件名以字符“_”(下划线)开头以表明它不是一个完整的模板。该模板将查找 is_finished 为 false 的文章并链接到这些文章。在终端窗口中执行以下命令: gedit app/views/articles/_unfinished.html.erb
|
. |
在该文件中添加以下代码: <div class="unfinished-title">Unfinished Articles</div>
|
. |
接着,需要在页面布局中引用这个新的“局部模板”以便所有页面显示它。在终端窗口中执行以下命令: gedit app/views/layouts/articles.html.erb
|
. |
紧随 <p style="color:green"><%= flash[:notice] %></p> 之后添加以下代码: <div id="unfinished">
|
. |
接着,需要编写新按钮将执行的 mark_finished 操作的代码。在终端窗口中执行以下命令: gedit app/controllers/articles_controller.rb
|
. |
向下滚动至文件底部。在最后一个“end”的前面添加以下代码: # POST /articles/mark_finished/1
|
. |
您已更新了数据库,向页面布局添加了按钮和操作以及列表。现在可对该功能进行测试了。在浏览器中输入以下 URL: http://localhost:3000/articles 注意页面顶部列出了未完成的文章。选择 Boning a Duck 链接。 单击 Mark Finished 按钮。 您会看到 Boning a Duck 已从 Unfinished Articles 列表中删除。选择 Back。
|
. |
此时您可以尝试 AJAX 了!您希望将应用程序更改成这样:当您按下该按钮时,窗口会自动更新而不会刷新整个屏幕。为此,您想让“Mark Finished”按钮发送一个 AJAX 命令来执行 mark_finished 操作,然后再发回一个命令更新“Unfinished Articles”标题下的内容。首先将该按钮更改为一个远程 (AJAX) 表单。在终端窗口中执行以下命令: gedit app/views/articles/show.html.erb
|
. |
将以下语句: <%= button_to "Mark Finished", :action => :mark_finished, :id => @article.id %> 更改为 <% form_remote_tag :url => { :action => :mark_finished, :id => @article } do %>
|
. |
当您按下该按钮时,应用程序将像以前一样进行更新,但不发送整个页面,您需要发送回某个 JavaScript 以便只更新未完成文章列表。通过使用一个远程 javascript 模板,Rails 可为您生成这个 JavaScript。在终端窗口中执行以下命令新建一个文件: gedit app/views/articles/mark_finished.js.rjs
|
. |
输入以下代码行: page.replace_html("unfinished" , :partial => "unfinished")
|
. |
为使其生效,在所有页面中需有一些默认的 JavaScript 子例程。您需要编辑布局。在终端窗口中执行以下命令新建一个文件: gedit app/views/layouts/articles.html.erb
|
. |
在 <%= stylesheet_link_tag 'scaffold' %> 之后添加下行: <%= javascript_include_tag :defaults %>
|
. |
接着,需要更新 mark_finished 操作以使用新的远程模板,该模板与该操作同名。在终端窗口中执行以下命令新建一个文件: gedit app/controllers/articles_controller.rb
|
. |
将以下代码: # POST /articles/mark_finished/1 更改为 # *AJAX* /articles/mark_finished/1
|
. |
您已转为使用一个 AJAX 请求表单并发回 Javascript 以更新列表。在浏览器中输入以下 URL: http://localhost:3000/articles 新建一个文章。选择 New article。 对 Title 输入 Gravity,对 Author 选择 Julia Child,对 Abstract 输入 Gravity makes cakes fall,然后单击 Create。 您会看到 Unfinished Articles 列表中列出了 Gravity。选择 Gravity 链接。 单击 Mark Finished。 Gravity 立即从列表中消失。该页面未完全刷新。这是 AJAX 的功劳。在像这样一个简单的屏幕上,使用和不使用 AJAX 之间的差别可能不太明显,因为您的 Web 服务器发送的页面较小。但在含有图像、flash 和/或大量数据的更为复杂的屏幕上,其差别可以是巨大的。如果使用 AJAX,则服务器可以只发送有变化的部分。因此,您确实会欣赏 Rails 对 AJAX 支持!
|
在本教程中,您学习了如何:
本教程的此部分给出了 Ruby 语言的概述。下面列出了您将遇到的对象。如果您熟悉 Ruby,可以跳过这一部分,继续下一步的学习。
|
在 Rails 中,如果您希望在“comics”表中添加“t.column :price, :float”列,执行以下步骤:
. |
现在可以生成 comic 模型。在终端窗口中执行以下命令: ruby script/generate migration add_columns
|
---|---|
. |
您想编辑生成的脚本。在终端窗口中输入以下命令: gedit db/migrate/008_add_columns.rb
|
. |
用以下内容替换 self.up 部分,然后保存并关闭该文件。 def self.up
|
. |
现在可以对数据库迁移进行 rake 操作,以生成目标表。在终端窗口中输入以下命令: rake db:migrate 注:要删除某列,我们可以在 self.up 方法中添加一行(如“remove_column :comics, :price”);要重命名某列,我们可以在 self.up 方法中添加一行(如“rename_column :comics, :price, :new_price”);要更改某列,我们可以在 self.up 方法中添加一行(如“change_column :comics, :price, :integer”)。
|
![]() |
关于 Oracle | ![]() |