ruby on rails
Ruby on Rails于2004年发布,已Swift成为Web应用程序开发中最流行的框架之一。 这个开源项目也称为Rails或RoR,它使用模型-视图-控制器(MVC)架构,Ruby面向对象的脚本语言以及简单的原则,例如“约定之上的配置”和“不要重复自己”。 因此,开发人员可以通过更少的冗余代码和配置文件,更快,更轻松地构建应用程序而受益,同时保留创建自定义扩展的灵活性,以满足他们的应用程序需求。 通过支持数据库持久性,可以使用数据库服务器和内置的WEBrick Web服务器轻松开发使用该框架的Web应用程序。
随着RubyForge社区门户网站上发布的IBM_DB Rails适配器和Ruby驱动程序的可用性,Ruby on Rails框架已经在所有DB2数据服务器上进行了正式测试和支持。 可能有些人对此感到惊讶,但是社区还可以使用DB2 9数据库的免费版本DB2 Express-C 。 DB2 Express-C数据服务器的免费开发,部署和分发没有大小,时间或用户限制,并且包含在Rails的Starter Toolkit中 。 该软件包帮助开发人员使用DB2在RoR环境中快速轻松地设置和构建Web应用程序。
尽管可以在Rails框架中配置各种数据存储,但是DB2数据服务器带来了一些独特而突出的优势。 自从DB2 9中引入pureXML™以来,一个主要的好处是,与IBM数据服务器一起使用时,IBM_DB适配器和驱动程序支持本机XML数据类型。
当前有两种使用DB2设置Rails开发环境的替代方法。 如果您不熟悉DB2环境,那么将DB2 on Rails入门工具包设计为启动DB2 on Rails应用程序开发的最便捷方法。 可从alphaWorks下载Starter Toolkit 2.1版,并安装稍旧的IBM_DB适配器版本。 该版本不支持i5和zOS平台上的DB2,但是正在进行更新,并且即将提供下载。
但是,如果您试图在现有的DB2环境中开发Rails应用程序,那么自从发布IBM_DB适配器和驱动程序gem和插件以来,一个同样轻松的“手动”选项已经可用。 请检查RubyForge rubyibm项目的最新版本(自4月30日起提供生产/稳定版本0.6.0)。
让我们首先下载并配置DB2 Express-C数据服务器和Rails运行时环境。 最新版本的IBM_DB适配器和驱动程序需要DB2 9,FixPack 2或DB2 8,FixPack15。要下载和配置DB2 Express-C数据服务器和Rails运行时环境:
安装Rails gem及其依赖项 :
gem install rails --include-dependencies
注1:之所以需要DB2 Client 9 FP2,是因为CLI修复(与数字引用有关)与IBM_DB驱动程序和适配器中的一些重要更改相关联。
注2: DB2 9上的大多数Rails应用程序要求的最低APPLHEAPSZ为1024。db2 db2 update db cfg for
要更新到db cfg,需要回收DB2( db2stop后跟db2start )。
这仅是手动安装IBM_DB适配器和驱动程序(方法2)的问题,因为该值是最新的DB2 on Rails Starter Toolkit中的缺省值。
为了帮助理解Ruby gem安装和Rails插件安装之间的区别,这里是运行时环境的简要说明。
RubyGems是Ruby运行时环境中库和应用程序的标准打包和安装框架。 然后,将每个软件包的一个文件(称为gem)按照软件包格式分发并存储在中央存储库中,从而允许同时部署同一库或应用程序的多个版本。 与Linux发行版打包管理和捆绑软件(.rpm,.deb)类似,也可以通过gem最终用户实用程序查询,安装,卸载和操作这些gem 。 gem实用程序可以无缝查询远程RubyForge中央存储库,还可以查找和安装许多易于使用的实用程序中的任何一个,这些实用程序使Rails开发人员的工作变得轻松。 一旦安装了IBM_DB gem,就可以通过Ruby运行时环境中的任何脚本(因此是应用程序)立即访问该功能:
作为ActiveRecord适配器,IBM_DB gem必须由抽象适配器在其RAILS_CONNECTION_ADAPTERS (active_record.rb)列表中注册,然后才能在Rails框架中使用。 注册后,将装入IBM_DB gem及其依赖项(ibm_db Ruby驱动程序以及ODBC和CLI的IBM驱动程序)。 这使Ruby环境中的任何应用程序(包括Rails)都可以与IBM数据服务器进行交互。 正如IBM_DB宝石README文件(见所描述的相关主题这篇文章的部分),每几个简单的步骤,Ruby运行时被访问的IBM数据服务器上启用。
注3:在Windows环境中,运行“ gem install ibm_db”时,每个版本都会为您提供两个选择(mswin32或ruby)。 通过选择“ mswin32”,将安装Windows的预构建二进制文件。
示例: D:\>gem install ibm_db
Bulk updating Gem source index for: http://gems.rubyforge.org
Select which gem to install for your platform (i386-mswin32)
1. ibm_db 0.6.0 (mswin32)
2. ibm_db 0.6.0 (ruby)
3. ibm_db 0.4.6 (ruby)
4. ibm_db 0.4.6 (mswin32)
5. Skip this gem
6. Cancel installationD:\>gem install ibm_db
Bulk updating Gem source index for: http://gems.rubyforge.org
Select which gem to install for your platform (i386-mswin32)
1. ibm_db 0.6.0 (mswin32)
2. ibm_db 0.6.0 (ruby)
3. ibm_db 0.4.6 (ruby)
4. ibm_db 0.4.6 (mswin32)
5. Skip this gem
6. Cancel installation
将IBM_DB适配器和驱动程序安装为Ruby Gem
发出gem命令安装IBM_DB适配器和驱动程序:
D:\>gem install ibm_db
在Rails框架的连接适配器列表中注册“ ibm_db”。
手动将ibm_db添加到gems \ 1.8 \ gems \ activerecord-1.15.3 \ lib \ active_record.rb中:
RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite ... ibm_db )
Rails插件代表框架自己的扩展机制。 这提供了Rails可以在特定的和单独的Rails应用程序范围内扩展其功能的方法。 结果,当未在Ruby运行时环境中部署IBM_DB gem时,这提供了另一种访问IBM数据服务器的方法。 尽管Rails插件不提供特定于Ruby gem的版本管理,但它们提供了有用的初始化机制,该机制允许IBM_DB插件在初始化期间自动插入Rails注册表。 因此,在将IBM_DB作为插件安装在您的应用程序中之后,Rails框架不需要手动步骤来加载它。 如RubyForge上的IBM_DB插件README文件和rubyibm项目文档中所述,只需注册插件源并运行Rails应用程序安装脚本, 就可以为IBM数据服务器访问启用Rails应用程序。 尽管RubyForge尚未启用对Subversion(SVN)存储库的HTTP访问(项目支持当前仅是SVN协议),但在Windows上安装Rails插件需要安装SVN客户端。 在大多数Linux®和UNIX®发行版上,默认情况下可以使用SVN客户端,这使得IBM_DB插件安装相当无缝。
IBM_DB适配器(ibm_db_adapter.rb)直接依赖于ibm_db驱动程序,该驱动程序利用IBM驱动程序进行开放式数据库连接(ODBC)和呼叫级别接口(CLI)连接到IBM数据服务器。 IBM CLI是可访问ODBC的IBM数据服务器SQL接口。
这对IBM_DB适配器和驱动程序有一些影响。
用于ODBC和CLI的IBM驱动程序的安装必须满足IBM_DB的要求。
您可以通过完整的DB2数据库安装获得ODBC和CLI的IBM驱动程序,或者从“ ODBC和CLI的IBM DB2驱动程序概述 ”中单独获得这些组件。
您可以使用CLI关键字在任何Ruby应用程序之外修改驱动程序行为。
您可以使用一些CLI关键字在Rails应用程序外部更改某些事务行为。 例如,您可以使用它们来设置当前架构或更改事务元素,例如关闭自动提交行为。 可以在以下DB2信息中心文档中找到有关CLI关键字的详细信息:
版本8
版本9
任何诊断收集都将需要CLI驱动程序跟踪功能。
由于通过IBM_DB驱动程序的所有请求都是使用IBM驱动程序提供的ODBC和CLI驱动程序提供的API来实现的,因此CLI跟踪是一种重要的跟踪机制,用于使用IBM_DB适配器和驱动程序识别应用程序中的问题。
CLI跟踪捕获应用程序对ODBC和CLI的IBM驱动程序进行的所有API调用(包括所有输入参数),并捕获从驱动程序返回给应用程序的所有值。 它是一个接口跟踪,旨在捕获应用程序如何与ODBC和CLI的IBM驱动程序进行交互,并提供有关驱动程序内部工作的信息。
版本8
版本9
在瞬息万变的环境中,应用程序需要动态适应以应对新的要求和挑战。 当应用程序开发人员更改其应用程序时(例如,在添加新对象或类时),需要修改基础持久性以确保数据库与应用程序同步。 更改数据库架构的传统方法是生成新SQL脚本。 但是,通过SQL脚本将应用程序和数据库保持在版本顺序中是一个挑战。 此外,数据库开发人员很少构建SQL脚本来撤消与应用程序更改相关联的数据库模式中所做的更改。 在大多数开发环境中,通过删除所有数据库对象并使用先前版本SQL(数据定义语言[DDL])脚本重新创建它们,可以撤消更改。
对于许多Web开发人员而言,Rails的主要启示是其对通过迁移进行模式演变的内置支持。 尽管数据库开发人员肯定更倾向于通过DDL或数据处理语言(DML)使用SQL,但是大多数应用程序开发人员仍然乐于坚持使用他们的工具:Ruby语言及其库。 这正是Rails通过迁移提供的功能:一个简单而有效的基础架构,它利用ActiveRecord抽象来创建和修改版本序列中的数据库对象,例如表和列。 Rails迁移完成了与架构演变相关的大多数数据库管理任务。 Rails框架简化了开发,但是关联的工具(瑞克任务)在驱动数据库更改并使应用程序代码与其表结构保持同步方面也非常有效。
Ruby on Rails迁移解决了上述一些涉及数据库和数据结构更改的问题。 现在,让我们看一下Rails迁移如何促进数据库模式的发展。
让我们检查一下使用IBM_DB适配器的Rails迁移示例,同时尝试进行一些与Rails应用程序演变有关的数据库对象更改。 但是首先,您需要确保如先前所述安装并配置了DB2 on Rails开发环境。
我们的示例将尝试构建一个Team Room,这是一个托管应用程序,使注册会员可以共享文本或二进制格式的各种文档,包括图像,可执行文件,演示文稿和任何其他媒体。 考虑到可以通过pureXML数据类型将它们本机存储在DB2 9中的难易程度,还包括要共享的XML文档。 此示例还将找到一些利用其内置层次结构的好方法。
首先,让我们创建一个名为“ teamroom”的Rails项目。
D:\rails>rails teamroom
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create components
create db
create log/server.log
create log/production.log
create log/development.log
create log/test.log
Rails框架自动生成项目的目录结构。 从这里开始,我们假设我们位于D:\ rails \ teamroom目录中,因此所有上述路径都是Team Room项目目录中的相对路径。
如果您已经有一个现有的DB2数据库,请跳过此步骤,然后直接继续执行步骤3,以开始配置数据库连接。
Rails项目和数据库 :您不需要为每个Rails项目创建一个新的数据库。 没有这样的一对一映射要求。
预期您可能会在某个时候想将XML本机存储在DB2中这一事实,让我们使用UTF-8代码集创建XMLDB数据库。 为了允许在DB2表中定义XML列,需要UTF-8代码集。
在DB2命令行处理器中,运行以下命令:
db2 create db xmldb using codeset utf-8 territory us
现在编辑D:\ rails \ teamroom \ config \ database.yml文件,以便我们可以连接到DB2 9 XMLDB数据库。
# IBM DB2 Database configuration file
#
# Install the IBM DB2 driver and get assistance from:
# http://www.alphaworks.ibm.com/tech/db2onrails
development:
adapter: ibm_db
database: xmldb
username: user
password: secret
schema: teamroom
application: TeamRoom
account: devuser
workstation: devbox
# == remote TCP/IP connection (required when no local database catalog entry available)
# host: bigserver // fully qualified hostname or IP address
# port: 50000 // data server TCP/IP port number
下表说明了DB2的每个连接属性:
连接属性 | 描述 | 需要 |
---|---|---|
适配器 | Ruby适配器名称,对于DB2,它是'ibm_db' | 是 |
数据库 | Rails项目连接到的数据库 | 是 |
用户名 | 用于连接到DB2数据库的用户标识 | 是 |
密码 | 指定的用户标识的密码 | 是 |
架构图 | 命名对象的集合。 该模式提供了一种在数据库内对对象进行逻辑分组的方法。 在此示例中,我们将Rails Team Room项目的所有数据库对象分组在“ teamroom”数据库模式下。 这允许多个Rails项目共享一个数据库。 | (可选)可以将默认架构设置为当前会话用户的授权ID。 (见注4 ) |
应用 | 使用DB2 Connect时,用于标识客户机应用程序名称的字符串被发送到主机数据库服务器。 在DB2 Connect上,发出“ db2列表应用程序”将显示“应用程序”名称,而不是Ruby可执行文件。 | 可选的 |
帐户 | 使用DB2 Connect时用于标识发送到主机数据库服务器的客户机记帐字符串的字符串 | 可选的 |
工作站 | 使用DB2 Connect时用于标识发送到主机数据库服务器的客户机工作站名称的字符串 | 可选的 |
主办 | 数据库所在的远程服务器的主机名 | 可选(请参阅注释5 ) |
港口 | 此参数包含数据库服务器将用来等待来自远程客户端的通信的TCP / IP端口的名称。 | 可选(请参阅注释5 ) |
注4:始终明确指定架构。
强烈建议您明确指定一个模式,以逻辑方式对数据库对象进行分组。 否则,如果使用相同的授权ID连接到由多个Rails项目共享的同一数据库,则多个Rails项目可能会无意中写入同一
注5:仅当DB2目录信息不可用并且在DB2 CLI的db2cli.ini配置文件中没有注册任何数据源时,才需要与远程TCP / IP连接关联的可选连接属性主机和端口 。 使用IBM Driver for ODBC和CLI代替本地安装的完整DB2 Client时,可以进行这种类型的设置。
现在,您准备开始执行实际的迁移步骤。
首先,您需要从存储区域开始,以便在此托管应用程序的用户之间共享所有文档和媒体文件。 因此,让我们创建DOCUMENTS表来存储团队成员想要共享的所有媒体文件。
让我们定义以下几列来描述共享文件的内容:
栏名 | 数据类型 | 描述 |
---|---|---|
ID | 整数 | 首要的关键 |
名称 | VARCHAR | 文件名称 |
尺寸 | 整数 | 文件大小 |
数据 | BLOB | 文件以二进制模式存储,最大大小为2 MB |
内容类型 | VARCHAR | 文档类型,包括文件类型,例如:.doc,.ppt,.pdf,.sw,.exe,.a,.so,.gif,.jpeg,.mov,.avi,.mpeg,.bmp等。 |
a)要通过迁移来执行此操作,请通过执行ruby script \ generate migration create_docs_store来为表DOCUMENTS 生成迁移 。 Rails生成迁移并创建db / migrate / 001_create_docs_store.rb。 您可以在UNIX上键入ruby script / generate migration create_docs_store 。 (请注意,反斜杠“ /”在Windows和UNIX上均适用。)
D:\rails\teamroom>ruby script/generate migration create_docs_store
create db/migrate
create db/migrate/001_create_docs_store.rb
注意001_ create_docs_store.rb。 在db / migrate中创建,并且编号为“ 001”。 从此步骤开始,将为每个迁移步骤以db / migrate生成顺序编号的文件。 这表明Rails正在为您管理迁移顺序。
b)编辑create_docs_store.rb如下所示:
class CreateDocsStore < ActiveRecord::Migration
def self.up
create_table :documents do |t|
t.column :name, :string, :null => false
t.column :size, :integer, :null => false
t.column :content_type, :string, :null => false
t.column :data, :binary, :limit => 2.megabytes
end
end
def self.down
drop_table :documents
end
end
注6:表名默认为复数形式。
默认情况下,Rails用复数形式标记表名。 运行上面的迁移将在DB2中创建一个名为DOCUMENTS
而不是DOCUMENT
。
注意7: rake db:migrate运行所有尚未应用的迁移。 在这种情况下,仅适用一次迁移。
在Rails应用程序中,架构更改是通过迁移进行的。 对数据库模式的每次更改都在Ruby脚本中进行版本控制和定义,该脚本包含与供应商无关的语法。 此外,在每个迁移脚本具有两种类方法的情况down
,撤消更改就像进行更改一样容易: up
方法和down
方法。 更改一个逻辑数据库架构所需的所有代码都放在self.up
方法中。 撤消更改所需的任何代码都放在self.down
方法中。
c)通过rake db:migrate命令运行迁移 :
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateDocsStore: migrating =================================================
-- create_table(:documents)
-> 0.2010s
== CreateDocsStore: migrated (0.2010s) ========================================
d)现在转到DB2命令提示符并为架构团队空间发出db2列表表,以确认已创建DOCUMENTS表:
D:\>db2 list tables for schema teamroom
Table/View Schema Type Creation time
------------------------------- --------------- ----- --------------------------
DOCUMENTS TEAMROOM T 2007-04-21-21.00.18.131001
SCHEMA_INFO TEAMROOM T 2007-04-21-21.00.17.740001
2 record(s) selected.
请注意,DOCUMENTS表是按预期创建的,其数据类型如下:
D:\>db2 describe table teamroom.documents
Column Type Type
name schema name Length Scale Nulls
------------------------------ --------- ------------------ -------- ----- ------
ID SYSIBM INTEGER 4 0 No
NAME SYSIBM VARCHAR 255 0 No
SIZE SYSIBM INTEGER 4 0 No
DATA SYSIBM BLOB 2097152 0 Yes
CONTENT_TYPE SYSIBM VARCHAR 255 0 No
5 record(s) selected.
注8:自动创建主键。
Rails中的默认主键列名称是id
。 您不必显式定义主键ID
列,因为默认情况下,Rails会为我们这样做。
还要注意,Rails在此迁移步骤中创建了另一个表SCHEMA_INFO。 SCHEMA_INFO是通过rake db:migrate命令创建的。 查询SCHEMA_INFO表显示以下输出:
D:\>db2 select * from schema_info
VERSION
-----------
1
1 record(s) selected.
版本列中的值“ 1”表示您正在迁移的版本1(回想一下您运行的是db / migrate / 001_ create_docs_store.rb)
因此rake db:migrate本质上执行以下所有操作:
up
方法。 第一次迁移从版本值'1'开始。 创建DOCUMENTS表之后,假设您决定要存储有关每个文档的其他信息,例如操作系统平台,上载时间和最后更改时间。 生成的DOCUMENTS表应包含以下列(要添加的新列以粗体突出显示 )
栏名 | 数据类型 | 描述 |
---|---|---|
ID | 整数 | 首要的关键 |
名称 | VARCHAR | 文件名称 |
尺寸 | 整数 | 文件大小 |
数据 | BLOB | 文件以二进制模式存储,最大大小为2 MB |
内容类型 | VARCHAR | 文档类型,包括文件类型,例如:.doc,.ppt,.pdf,.sw,.exe,.a,.so,.gif,.jpeg,.mov,.avi,.mpeg,.bmp等。 |
Created_at | 时间戳 | 上传文件的时间 (请参见注释9 ) |
Updated_at | 时间戳 | 文档上次更新时间戳 (请参阅注释9 ) |
平台 | VARCHAR | 文件平台特定信息 |
注9:选择的两列名称created_at
和updated_at
带有Rails的特殊语义。 与其他“魔术列名称”( id, type, position, lock_version, parent_id>
)一样,Rails将使用此名称作为约定。 在这种情况下,它将自动以创建行或上次更新的时间戳进行更新。 它仅要求基础数据库列能够接收日期,日期时间或字符串。 完整的Rails约定是对于日期列使用_on
后缀,对于包含时间的列使用_at
后缀。
您生成第二次迁移,以将这些属性添加到DOCUMENTS表中:
a)运行ruby脚本/生成迁移add_docs_attributes 。
这将生成db / migrate / 002_add_docs_attributes.rb文件。
D:\rails\teamroom>ruby script/generate migration add_docs_attributes
exists db/migrate
create db/migrate/002_add_docs_attributes.rb
注10:迁移的想法是,如果您需要更改持久性数据库中的任何内容,则将生成一个新的迁移以执行更改。 您永远不会编辑原始迁移以进行更改。
b)编辑002_add_docs_attributes.rb如下所示:
class AddDocsAttributes < ActiveRecord::Migration
def self.up
add_column :documents, :created_at, :timestamp
add_column :documents, :updated_at, :timestamp
add_column :documents, :platform, :string, :limit => 10
end
def self.down
remove_column :documents, :created_at
remove_column :documents, :updated_at
remove_column :documents, :platform
end
end
注意11:您可以使用add_column
在self.up
方法中添加属性。 要还原更改,请使用remove_column
。
c)再次发出rake db:migrate以执行第二次迁移。
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== AddDocsAttributes: migrating ===============================================
-- add_column(:documents, :created_at, :timestamp)
-> 0.0500s
-- add_column(:documents, :updated_at, :timestamp)
-> 0.0100s
-- add_column(:documents, :platform, :string, {:limit=>10})
-> 0.0000s
== AddDocsAttributes: migrated (0.0600s) ======================================
注意12:您可以再次使用db2 describe table teamroom.documents
来验证新列是否已添加到DOCUMENTS表中。
注意13:
是对表名为
的复数形式的外键引用的默认名称。 外键等关联是通过模型关系在Rails中实现的。 框架用于管理此模型关系的重要约定之一是表的主键列的默认名称(其id
),而对该表的外键引用的默认名称为
(表名具有
的复数形式)。 重要的是要了解,Rails迁移未定义外键约束。 在开发人员使用表中的键值以某种关系填充列时,将设置表之间的关系。 建议您还通过迁移在数据库中建立和实施此类约束,但这不是Rails框架的要求。
组织或社区中的许多人会对这些文档感兴趣,因此您需要一种管理此类用户及其访问权限的方法。 因此,让我们添加一个USERS表来实现此目的。 您还需要在DOCUMENTS表中添加外键'user_id',以便了解上载特定文档的用户。
这些是执行这些任务所需的步骤:
a)运行ruby脚本/生成迁移create_users_table ,它将创建db / migrate / 003_create_users_table.rb文件
b)如下编辑db / migrate / 003_create_users_table.rb文件:
class CreateUsersTable < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :usertype, :string, :limit => 5, :null => false
t.column :firstname, :string, :limit => 30
t.column :lastname, :string, :limit => 30
t.column :extension, :string, :limit => 4
end
add_column :documents, :user_id, :integer
end
def self.down
drop_table :users
remove_column :documents, :user_id
end
end
c)运行rake db:migrate创建USERS表:
D:\rails\teamroom>rake db:migrate
(in D:/rails/teamroom)
== CreateUsersTable: migrating ================================================
-- create_table(:users)
-> 0.1400s
-- add_column(:documents, :user_id, :integer)
-> 0.0000s
== CreateUsersTable: migrated (0.1400s) =======================================
d)您现在可以发出ruby脚本/生成支架文件来为DOCUMENTS表生成支架。 脚手架通过提供标准化的动作来列出,显示,创建,更新和销毁该类的对象,从而使Active Record类快速上线。 如下面的清单15所示,在生成支架时,在/ app / controllers和/ app / views中创建了一个控制器和许多视图。
D:\rails\teamroom>ruby script/generate scaffold document
exists app/controllers/
exists app/helpers/
create app/views/documents
create app/views/layouts/
create test/functional/
dependency model
create app/models/
exists test/unit/
exists test/fixtures/
create app/models/document.rb
create test/unit/document_test.rb
create test/fixtures/documents.yml
create app/views/documents/_form.rhtml
create app/views/documents/list.rhtml
create app/views/documents/show.rhtml
create app/views/documents/new.rhtml
create app/views/documents/edit.rhtml
create app/controllers/documents_controller.rb
create test/functional/documents_controller_test.rb
create app/helpers/documents_helper.rb
create app/views/layouts/documents.rhtml
create public/stylesheets/scaffold.css
此时,您准备好看看脚手架对我们的作用。 在命令提示符下,键入ruby script / server以启动Rails的内置WEBrick Web服务器:
D:\rails\teamroom>ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-04-26 16:54:57] INFO WEBrick 1.3.1
[2007-04-26 16:54:57] INFO ruby 1.8.5 (2006-12-25) [i386-mswin32]
[2007-04-26 16:54:57] INFO WEBrick::HTTPServer#start: pid=444 port=3000
记下端口号。 缺省值为3000,但是如果系统上已经使用了端口3000,则可能会有所不同。 打开Web浏览器,然后转到http:// localhost:3000 /,您会注意到“欢迎登机”消息。 浏览到http:// localhost:3000 / documents,您将看到以下内容:
e)编辑生成的/app/models/document.rb文件,如下所示:
class Document < ActiveRecord::Base
belongs_to :user
end
belongs_to表示DOCUMENTS和USERS表之间的一对一外键关系。 这种关联表明每个文档只能与一个用户关联(属于)。 如果DOCUMENTS表具有user_id
外键列,则文档模型belongs_to :user
。
注14:包含外键的表的模型始终具有belongs_to
声明。
我们在/app/models/document.rb中添加了其他代码,以便我们实际上可以上载文档并将文件存储在DB2 9数据库中。 请参阅下载部分以获取代码实现。 因此,在将许多文档添加到我们的团队室之后,您将在浏览器中看到类似的内容:
f)同样,发出ruby脚本/生成支架用户以为Users表生成支架。 然后编辑/app/models/user.rb如下所示:
class User < ActiveRecord::Base
has_many :document
end
注意15: has_many
关联表示用户可以上传多个文档。
注意16:有关ActiveRecord关联的更多信息,请参见http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html 。
既然您已经详细了解了最初的几个迁移步骤,那么让我们简要介绍一下其余的迁移过程,以创建所需的其余表和关联。
当然,有一种方法可以对社区将贡献的大量文档进行分类,因此可以添加基于内容主题的分类法。 SUBJECTS表将被创建以帮助分类我们的文档。 一个主题包含许多文档,但是每个文档只能属于一个主题。 为了说明主题和文档之间的一对多关系,我们需要在文档中添加一个主题ID外键。
这些是执行这些任务所需的步骤:
a)运行ruby脚本/生成迁移create_subjects_table ,它将创建db / migrate / 004_create_subjects_table.rb文件。
b)如下编辑db / migrate / 004_create_subjects_table.rb:
class CreateSubjectsTable < ActiveRecord::Migration
def self.up
create_table :subjects do |t|
t.column :name, :string, :limit => 20
t.column :size, :integer
t.column :description, :text
t.column :tag, :string, :limit => 10
end
add_column :documents, :subject_id, :integer
end
def self.down
drop_table :subjects
remove_column :documents, :subject_id
end
end
c)运行rake db:migrate创建SUBJECTS表,并添加subject_id
外键。
d)运行ruby脚本/生成支架主题以为SUBJECTS表生成支架。
e)将has_many :document
关联添加到新生成的/app/models/subject.rb文件中。
class Subject < ActiveRecord::Base
has_many :document
end
f)在先前在步骤3(d)中生成的/app/models/document.rb文件中添加第二个关联属地belongs_to :subject
_subject。
class Document < ActiveRecord::Base
belongs_to :user
belongs_to :subject
<... code to assist with document uploading ...>
<... ...>
end
end
如果将新文档上载到特定类别时可以通知任何用户怎么办? 如果您可以在SUBSCRIPTIONS表中收集此类通知请求,则可以轻松实现。 用户,主题和订阅之间的某些关系也需要考虑。
让我们首先描述用户案例场景:用户Anthony有兴趣在新文档上载于某些主题上时接收通知:编程,Linux和钓鱼。 他将浏览到显示到目前为止创建的所有主题的页面,然后选中与上面列出的主题相关的框。 之后,每次在三个主题中的任何一个上载新文档时,应用程序都会生成一条通知消息,通过电子邮件发送给包含这些主题的任何订阅的所有者。 所有这些将转化为以下一组关系:
您将使用与之前使用的迁移步骤非常相似的迁移步骤来实现这些数据库设计目标:
a)运行ruby脚本/生成迁移create_subscriptions_table将创建db / migrate / 005_create_subscriptions_table.rb文件。
b)编辑db / migrate / 005_create_subscriptions_table.rb:
class CreateSubscriptionsTable < ActiveRecord::Migration
def self.up
create_table :subscriptions do |t|
t.column :name, :string, :limit => 20
t.column :description, :text
t.column :user_id, :integer
end
add_column :subjects, :subscription_id, :integer
end
def self.down
drop_table :subscriptions
remove_column :subjects, :subscription_id
end
end
c)运行rake db:migrate创建SUBSCRIPTIONS表,并将外键列添加到SUBJECTS。
d)运行ruby脚本/生成脚手架订阅以生成SUBSCRIPTIONS的脚手架。
e)将has_many :subject
关联添加到在步骤4 d生成的/app/models/subscription.rb文件中。
f)在新生成的/app/models/subject.rb文件中添加一个对应的关联belongs_to :subscription
g)将has_one :subscription
关联添加到在步骤3 f中生成的/app/models/user.rb文件中。
h)将belongs_to :user
关联添加到新生成的/app/models/subscription.rb文件中。
注17:细心的读者肯定会发现不一致的地方,这会导致当前的订阅设计不完全真实或可用:主题只能属于订阅,因此,一旦Anthony在其订阅页面中对其进行检查,它将不再对Bob可用。 。 显然,这是一个多对多的关系,但是会使它变得简单(例如,现在没有中间联接表)。 它肯定会在本系列的第2部分中修复。
向我们的用户通知Team Room更新的一种方法是通过电子邮件。 为此,您需要为每个用户添加电子邮件联系人,因此通过另一次迁移将电子邮件列添加到USERS表:
a)运行ruby脚本/生成迁移addEmailToUser 。 这将生成db / migrate / 006_add_email_to_user.rb文件。
b)编辑006_add_email_to_user.rb。
class AddEmailToUser < ActiveRecord::Migration
def self.up
add_column :users, :email, :string, :limit => 30
end
def self.down
remove_column :users, :email
end
end
c)运行rake db:migrate将电子邮件列添加到USERS表。
下面的图表说明了您在步骤1到步骤6中所做的事情。
Increasingly often in today's enterprise environment, documents need to be stored in the XML format, and such remarkable structured documents are not always treated much different from some amorphous binary objects. We dare to try something different in this application, while storing XML documents in a data type different from the BLOB data type already defined in the DOCUMENTS table.
We can afford that while using a DB2 9 data server, and taking advantage of the native XML data persistence, which enables well-formed XML documents to be stored in their hierarchical form. XML columns are declared in DB2 9 as XML data types, and this is precisely what we will use in the new migration.
a) Run ruby script/generate migration add_xml_doc_column .
This generates db/migrate/007_add_xml_doc_column.rb
.
b) Edit 007_add_xml_doc_column.rb
:
class AddXmlDocColumn < ActiveRecord::Migration
def self.up
add_column :documents, :xmldata, :xml
end
# Currently, a column that is part of a table containing an XML column
# cannot be dropped. To remove the column, the table must be dropped
# and recreated without the previous XML column.
def self.down
drop_table :documents
create_table :documents do |t|
t.column :name, :string, :null => false
t.column :size, :integer, :null => false
t.column :data, :binary, :limit => 2.megabytes
t.column :content_type, :string, :null => false
t.column :created_at, :timestamp
t.column :updated_at, :timestamp
t.column :platform, :string, :limit => 10
t.column :user_id, :integer
t.column :subject_id, :integer
end
end
end
c) Run rake db:migrate to add the new column to the DOCUMENTS table.
While the add_column
looks already familiar, you might be surprised to see the entire table needs to be dropped and then recreated, instead of using the remove_column
. This should come as no surprise, given the important changes that the XML brings to the table as a native data type. Although this can be perceived as a relative inconvenience until XML column removal is supported, in the next part of this series, we will present an alternative database schema design, and also the major advantages the native XML data type support brings in exchange. But first, let's gain experience with this previously considered "amorphous" blob of data.
d) Analyze marketing data collected and formatted in an XML document.
Let's try to determine all Toronto neighbourhoods represented in the marketing data collected, by extracting customer's postal code information from one of the documents posted in the Team Room. Use the documents scaffold while browsing to http://localhost:3000/ and upload the teamroom/test/fixtures/CAN-Central.xml
document provided with the sample code. Then, add the following action in the documents_controller.rb
:
def zips
@id = params[:id]
@xmldata = Document.find_by_sql "select xmlquery(\
'\
{for $i in $t/marketinfo/sales/customer/address\
where $i/city = \"Toronto\"\
return {$i/zip/text()} } \
'\
passing c.xmldata as \"t\")\
from documents c where id = #{@id}"
p @xmldata[0]
redirect_to :action => 'list'
end
For the current stage of this application, the result of this complex SQL and embedded XQuery is only printed in your server console while following the zips link for the CAN-Central.xml document previously uploaded. The result will contain the list of postal code areas associated with Toronto customers existing in the CAN-Central.xml
document. The XQuery embedded into the SQL statement might look complicated at first sight, but in most cases an XPath query expression could simplify:
Document.find_by_sql "select xmlquery('\
{$t/marketinfo/sales/customer/address/zip[../city = \"Toronto\"]}\
' passing c.xmldata as \"t\")\
from documents c where id = #{@id}"
In the next part of this series, we will find better ways to simplify Rails application interaction through SQL embedded XQuery and XPath expression. For the time being, rest assured that you will no longer need to retrieve the entire content of large XML documents to merely inspect a small fraction of it. It can be done inside the DB2 native XML data store, while taking advantage of the DB2 engine optimizer.
Figure 4 shows what the Team Room database objects should look like at the end of Step 7:
Finally, we are done. But what if we want to undo all the changes now? This is very simple, just run rake db:migrate VERSION= number where number indicates the version you wish to rollback to. For example, if you wanted to destroy the tables we created for the Rails Team Room project in the XMLDB database and undo all the changes you have made so far, you would issue rake db:migrate VERSION=0 . Rails reverses each migration step in order, rolling back the changes for the largest migration first, eventually downgrading the database to version 0 as specified.
D:\rails\teamroom>rake db:migrate VERSION=0
(in D:/rails/teamroom)
== AddXmlDocColumn: reverting =================================================
-- drop_table(:documents)
-> 0.0150s
-- create_table(:documents)
-> 0.1880s
== AddXmlDocColumn: reverted (0.2030s) ========================================
== AddEmailToUser: reverting ==================================================
-- remove_column(:users, :email)
-> 0.1250s
== AddEmailToUser: reverted (0.1250s) =========================================
== CreateSubscriptionsTable: reverting ========================================
-- drop_table(:subscriptions)
-> 0.0000s
-- remove_column(:subjects, :subscription_id)
-> 0.1560s
== CreateSubscriptionsTable: reverted (0.1560s) ===============================
== CreateSubjectsTable: reverting =============================================
-- drop_table(:subjects)
-> 0.0000s
-- remove_column(:documents, :subject_id)
-> 0.1570s
== CreateSubjectsTable: reverted (0.1570s) ====================================
== CreateUsersTable: reverting ================================================
-- drop_table(:users)
-> 0.0000s
-- remove_column(:documents, :user_id)
-> 0.1400s
== CreateUsersTable: reverted (0.1400s) =======================================
== AddDocsAttributes: reverting ===============================================
-- remove_column(:documents, :created_at)
-> 0.1250s
-- remove_column(:documents, :updated_at)
-> 0.1870s
-- remove_column(:documents, :platform)
-> 0.1260s
== AddDocsAttributes: reverted (0.4380s) ======================================
== CreateDocsStore: reverting =================================================
-- drop_table(:documents)
-> 0.0000s
== CreateDocsStore: reverted (0.0000s) ========================================
We presented how to get started with Rails application development using IBM_DB adapter/driver and DB2 data servers. The Starter Toolkit for DB2 on Rails provides the easiest method for those who are new to DB2 and Ruby on Rails, but for existing DB2 developers, the IBM_DB adapter and driver gem or plugin installation will provide a similarly easy entry.
We have also discussed Rails migration in detail. Managing database schema changes can be tedious. The Rails migration feature helps application developers manage this schema evolution, making it easy to synchronize changes between the application code and the database objects. By utilizing Rails migration and defining your database schema changes in Ruby files, versioning of changes takes place in a logical manner. Furthermore, because Rails' ActiveRecord is not vendor specific, a developer only needs to create a single Ruby migration file to handle the same changes over multiple database platforms while using various ActiveRecord adapters.
Stay tuned for Part 2 of the Ruby on Rails Series, where we will showcase how to take DB2 on Rails and XML support to the next level! XML manipulation through Ruby on Rails will be discussed in further detail.
翻译自: https://www.ibm.com/developerworks/data/library/techarticle/dm-0705chun/index.html
ruby on rails