ruby on rails_DB2和Ruby on Rails入门

ruby on rails

Ruby on Rails于2004年发布,已Swift成为Web应用程序开发中最流行的框架之一。 这个开源项目也称为Rails或RoR,它使用模型-视图-控制器(MVC)架构,Ruby面向对象的脚本语言以及简单的原则,例如“约定之上的配置”和“不要重复自己”。 因此,开发人员可以通过更少的冗余代码和配置文件,更快,更轻松地构建应用程序而受益,同时保留创建自定义扩展的灵活性,以满足他们的应用程序需求。 通过支持数据库持久性,可以使用数据库服务器和内置的WEBrick Web服务器轻松开发使用该框架的Web应用程序。

IBM_DB给Rails带来了什么?

随着RubyForge社区门户网站上发布的IBM_DB Rails适配器和Ruby驱动程序的可用性,Ruby on Rails框架已经在所有DB2数据服务器上进行了正式测试和支持。 可能有些人对此感到惊讶,但是社区还可以使用DB2 9数据库的免费版本DB2 Express-C 。 DB2 Express-C数据服务器的免费开发,部署和分发没有大小,时间或用户限制,并且包含在RailsStarter Toolkit中 。 该软件包帮助开发人员使用DB2在RoR环境中快速轻松地设置和构建Web应用程序。

尽管可以在Rails框架中配置各种数据存储,但是DB2数据服务器带来了一些独特而突出的优势。 自从DB2 9中引入pureXML™以来,一个主要的好处是,与IBM数据服务器一起使用时,IBM_DB适配器和驱动程序支持本机XML数据类型。

DB2 on Rails入门

当前有两种使用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 ruby​​ibm项目的最新版本(自4月30日起提供生产/稳定版本0.6.0)。

使用DB2 Express-C 9的手动分步安装

让我们首先下载并配置DB2 Express-C数据服务器和Rails运行时环境。 最新版本的IBM_DB适配器和驱动程序需要DB2 9,FixPack 2或DB2 8,FixPack15。要下载和配置DB2 Express-C数据服务器和Rails运行时环境:

  • 请访问以下网站并下载DB2 Express-C 9 FixPack 2
  • 安装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 <database_name> using APPLHEAPSZ 1024

要更新到db cfg,需要回收DB2( db2stop后跟db2start )。

这仅是手动安装IBM_DB适配器和驱动程序(方法2)的问题,因为该值是最新的DB2 on Rails Starter Toolkit中的缺省值。

与Rails插件相比,将IBM_DB适配器和驱动程序安装为Ruby gem

为了帮助理解Ruby gem安装和Rails插件安装之间的区别,这里是运行时环境的简要说明。

RubyGems是Ruby运行时环境中库和应用程序的标准打包和安装框架。 然后,将每个软件包的一个文件(称为gem)按照软件包格式分发并存储在中央存储库中,从而允许同时部署同一库或应用程序的多个版本。 与Linux发行版打包管理和捆绑软件(.rpm,.deb)类似,也可以通过gem最终用户实用程序查询,安装,卸载和操作这些gem 。 gem实用程序可以无缝查询远程RubyForge中央存储库,还可以查找和安装许多易于使用的实用程序中的任何一个,这些实用程序使Rails开发人员的工作变得轻松。 一旦安装了IBM_DB gem,就可以通过Ruby运行时环境中的任何脚本(因此是应用程序)立即访问该功能:

  • 需要“ ruby​​gems”
  • gem'ibm_db'(在Rubygems 0.9中已弃用了require_gem并由gem代替)

作为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 installation
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 installation

将IBM_DB适配器和驱动程序安装为Ruby Gem

  1. 发出gem命令安装IBM_DB适配器和驱动程序:

    D:\>gem install ibm_db
  2. 在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适配器和驱动程序有一些影响。

  1. 用于ODBC和CLI的IBM驱动程序的安装必须满足IBM_DB的要求。

    您可以通过完整的DB2数据库安装获得ODBC和CLI的IBM驱动程序,或者从“ ODBC和CLI的IBM DB2驱动程序概述 ”中单独获得这些组件。

  2. 您可以使用CLI关键字在任何Ruby应用程序之外修改驱动程序行为。

    您可以使用一些CLI关键字在Rails应用程序外部更改某些事务行为。 例如,您可以使用它们来设置当前架构或更改事务元素,例如关闭自动提交行为。 可以在以下DB2信息中心文档中找到有关CLI关键字的详细信息:

    版本8

    版本9

  3. 任何诊断收集都将需要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框架简化了开发,但是关联的工具(瑞克任务)在驱动数据库更改并使应用程序代码与其表结构保持同步方面也非常有效。

使用Rails迁移的DB2模式演变

Ruby on Rails迁移解决了上述一些涉及数据库和数据结构更改的问题。 现在,让我们看一下Rails迁移如何促进数据库模式的发展。

让我们检查一下使用IBM_DB适配器的Rails迁移示例,同时尝试进行一些与Rails应用程序演变有关的数据库对象更改。 但是首先,您需要确保如先前所述安装并配置了DB2 on Rails开发环境。

我们的示例将尝试构建一个Team Room,这是一个托管应用程序,使注册会员可以共享文本或二进制格式的各种文档,包括图像,可执行文件,演示文稿和任何其他媒体。 考虑到可以通过pureXML数据类型将它们本机存储在DB2 9中的难易程度,还包括要共享的XML文档。 此示例还将找到一些利用其内置层次结构的好方法。

  1. 首先,让我们创建一个名为“ teamroom”的Rails项目。

    清单1.创建Team Room 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
          
    <etc ......>
    
          create  log/server.log
          create  log/production.log
          create  log/development.log
          create  log/test.log

    Rails框架自动生成项目的目录结构。 从这里开始,我们假设我们位于D:\ rails \ teamroom目录中,因此所有上述路径都是Team Room项目目录中的相对路径。

  2. 如果您已经有一个现有的DB2数据库,请跳过此步骤,然后直接继续执行步骤3,以开始配置数据库连接。

    Rails项目和数据库 :您不需要为每个Rails项目创建一个新的数据库。 没有这样的一对一映射要求。

    预期您可能会在某个时候想将XML本机存储在DB2中这一事实,让我们使用UTF-8代码集创建XMLDB数据库。 为了允许在DB2表中定义XML列,需要UTF-8代码集。

    在DB2命令行处理器中,运行以下命令:

    清单2.创建XMLDB数据库
    db2 create db xmldb using codeset utf-8 territory us
  3. 现在编辑D:\ rails \ teamroom \ config \ database.yml文件,以便我们可以连接到DB2 9 XMLDB数据库。

    清单3.编辑database.yml文件
    # 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的每个连接属性:

表1. database.yml的可用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项目可能会无意中写入同一<AuthID> .schema_info表。 这将产生不可预测的结果。 Schema_info表用于跟踪迁移版本。 下面的团队室示例中提供了进一步的说明。

注5:仅当DB2目录信息不可用并且在DB2 CLI的db2cli.ini配置文件中没有注册任何数据源时,才需要与远程TCP / IP连接关联的可选连接属性主机和端口 。 使用IBM Driver for ODBC和CLI代替本地安装的完整DB2 Client时,可以进行这种类型的设置。

团队室示例

现在,您准备开始执行实际的迁移步骤。

步骤1:创建文档表

首先,您需要从存储区域开始,以便在此托管应用程序的用户之间共享所有文档和媒体文件。 因此,让我们创建DOCUMENTS表来存储团队成员想要共享的所有媒体文件。

让我们定义以下几列来描述共享文件的内容:

表2. 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上均适用。)

清单4.运行ruby脚本/生成迁移create_docs_store
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如下所示:

清单5.编辑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命令运行迁移

清单6.运行第一个迁移以创建DOCUMENTS表
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表:

清单7.列出创建的DB2表
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表是按预期创建的,其数据类型如下:

清单8.检查为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表显示以下输出:

清单9.查询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本质上执行以下所有操作:

  • 如果不存在则创建SCHEMA_INFO表,并将值'0'插入到version列中
  • 运行所有适用的迁移。 也就是说,它以升序运行数量大于当前迁移数的所有迁移的up方法。 第一次迁移从版本值'1'开始。
  • 使用迁移运行的最新版本更新SCHEMA_INFO表。 在上面的示例中,该版本已更新为“ 1”,因为它是该Rails项目的首次迁移。

步骤2:与文档关联的其他属性

创建DOCUMENTS表之后,假设您决定要存储有关每个文档的其他信息,例如操作系统平台,上载时间和最后更改时间。 生成的DOCUMENTS表应包含以下列(要添加的新列以粗体突出显示

表3. 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_atupdated_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文件。

清单10.创建第二个迁移以向DOCUMENTS表添加列
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如下所示:

清单11.查询SCHEMA_INFO表
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_columnself.up方法中添加属性。 要还原更改,请使用remove_column

c)再次发出rake db:migrate以执行第二次迁移。

清单12.运行第二次迁移以向DOCUMENTS表添加其他列
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: <model_name>_id是对表名为<model_name>的复数形式的外键引用的默认名称。 外键等关联是通过模型关系在Rails中实现的。 框架用于管理此模型关系的重要约定之一是表的主键列的默认名称(其id ),而对该表的外键引用的默认名称为<model_name>_id (表名具有<model_name>的复数形式)。 重要的是要了解,Rails迁移未定义外键约束。 在开发人员使用表中的键值以某种关系填充列时,将设置表之间的关系。 建议您还通过迁移在数据库中建立和实施此类约束,但这不是Rails框架的要求。

步骤3:管理用户及其对资源的访问

组织或社区中的许多人会对这些文档感兴趣,因此您需要一种管理此类用户及其访问权限的方法。 因此,让我们添加一个USERS表来实现此目的。 您还需要在DOCUMENTS表中添加外键'user_id',以便了解上载特定文档的用户。

这些是执行这些任务所需的步骤:

a)运行ruby脚本/生成迁移create_users_table ,它将创建db / migrate / 003_create_users_table.rb文件

b)如下编辑db / migrate / 003_create_users_table.rb文件:

清单13.编辑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表:

清单14.通过迁移创建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中创建了一个控制器和许多视图。

清单15.为文档创建一个支架
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服务器:

清单16:启动内置的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,您将看到以下内容:

图1.列出文件
数据库架构图

e)编辑生成的/app/models/document.rb文件,如下所示:

清单17:编辑/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数据库中。 请参阅下载部分以获取代码实现。 因此,在将许多文档添加到我们的团队室之后,您将在浏览器中看到类似的内容:

图2.列出文档
列表文档

f)同样,发出ruby脚本/生成支架用户以为Users表生成支架。 然后编辑/app/models/user.rb如下所示:

清单18:编辑/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

既然您已经详细了解了最初的几个迁移步骤,那么让我们简要介绍一下其余的迁移过程,以创建所需的其余表和关联。

步骤4:管理不断增长的共享文档集合

当然,有一种方法可以对社区将贡献的大量文档进行分类,因此可以添加基于内容主题的分类法。 SUBJECTS表将被创建以帮助分类我们的文档。 一个主题包含许多文档,但是每个文档只能属于一个主题。 为了说明主题和文档之间的一对多关系,我们需要在文档中添加一个主题ID外键。

这些是执行这些任务所需的步骤:

a)运行ruby脚本/生成迁移create_subjects_table ,它将创建db / migrate / 004_create_subjects_table.rb文件。

b)如下编辑db / migrate / 004_create_subjects_table.rb:

清单19:创建SUBJECTS表
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文件中。

清单20:向主题模型添加关联
class Subject < ActiveRecord::Base
  has_many :document
end

f)在先前在步骤3(d)中生成的/app/models/document.rb文件中添加第二个关联属地belongs_to :subject _subject。

清单21:将关联添加到文档模型
class Document < ActiveRecord::Base
  belongs_to :user
  belongs_to :subject

  <... code to assist with document uploading ...>
  <...                                        ...>
  
  end
end

步骤5:管理用户通知需求

如果将新文档上载到特定类别时可以通知任何用户怎么办? 如果您可以在SUBSCRIPTIONS表中收集此类通知请求,则可以轻松实现。 用户,主题和订阅之间的某些关系也需要考虑。

让我们首先描述用户案例场景:用户Anthony有兴趣在新文档上载于某些主题上时接收通知:编程,Linux和钓鱼。 他将浏览到显示到目前为止创建的所有主题的页面,然后选中与上面列出的主题相关的框。 之后,每次在三个主题中的任何一个上载新文档时,应用程序都会生成一条通知消息,通过电子邮件发送给包含这些主题的任何订阅的所有者。 所有这些将转化为以下一组关系:

  • 每个用户最多可以有一个订阅,但是订阅不是强制性的(例如,一对一,一个...关系)。
    • 需要将外键user_id添加到SUBSCRIPTIONS表中
    • 用户和订阅模型之间需要包含一对一关系
  • 每个用户订阅都可以包括一些首选主题(例如,一对多关系)。 将为用户提供一些从所有可用主题中进行选择的方法。
    • 需要将外键subscription_id添加到SUBJECTS表中
    • 订阅模型和主题模型之间需要包含一对多关系

您将使用与之前使用的迁移步骤非常相似的迁移步骤来实现这些数据库设计目标:

a)运行ruby脚本/生成迁移create_subscriptions_table将创建db / migrate / 005_create_subscriptions_table.rb文件。

b)编辑db / migrate / 005_create_subscriptions_table.rb:

清单22:创建SUBSCRIPTIONS表
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部分中修复。

步骤6:管理使用者联络人

向我们的用户通知Team Room更新的一种方法是通过电子邮件。 为此,您需要为每个用户添加电子邮件联系人,因此通过另一次迁移将电子邮件列添加到USERS表:

a)运行ruby脚本/生成迁移addEmailToUser 。 这将生成db / migrate / 006_add_email_to_user.rb文件。

b)编辑006_add_email_to_user.rb。

清单23:将电子邮件信息添加到USERS表
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中所做的事情。

图3.不同模型之间的关联
数据库架构图

步骤7:在工作室中存储XML文档

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 :

Listing 24: Adding XML column to DOCUMENTS
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 :

Listing 25: Analyzing XML format marketing data
def zips
  @id = params[:id]
  @xmldata = Document.find_by_sql "select xmlquery(\
                                      '<zipcodes>\
                                         {for $i in $t/marketinfo/sales/customer/address\
                                            where  $i/city = \"Toronto\"\
                                            return <zip>{$i/zip/text()}</zip>} \
                                      </zipcodes>'\
                                      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:

Listing 26: Finding postal code in city of Toronto from XML marketing data
Document.find_by_sql "select xmlquery('<zipcodes>\
                      {$t/marketinfo/sales/customer/address/zip[../city = \"Toronto\"]}\
                                       </zipcodes>' 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:

Figure 4. Team Room database schema diagram
Database schema diagram

Rolling back the changes through migration

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.

Listing 27. Reverting all the changes through migration
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

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值