2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

Rails 中精彩的图表

  • 2010-06-07
  • 本文字数:5751 字

    阅读完需:约 19 分钟

当分析完数据库中的数据,需要将结果以某种形式展示给用户的时候,有些 Web 应用程序比较偏好采用报告的形式。不过,图表的优点是能够根据报告,给出直观的视觉展现,并且可以帮助开发者观察趋势以及简化数据的综合分析过程。有很多技术能够帮助开发者构建出这类应用程序,Ruby on Rails 就是其中之一。在本文中,我们将会详细介绍如何使用 Ruby on Rails 创建图表。

优秀的软件能够从数据库中的数据或者报告中快速高效地生成图表。Gruff、JFreeChart、XML/SWF charts 和 FusionCharts 是 Ruby on Rails 上为数不多能满足我们需求的软件。不过你得明白,并不是所有这些软件我们都试用和测试过,所以下面的信息大部分是取自产品文档。

类型 Ruby 类 Java Class 文件 Flash 图表组件 Flash 图表组件 Flash 图表组件 操作系统平台 平台独立 平台独立 平台独立 平台独立 平台独立 是否需要 Adobe Flash 插件 不是 不是 是 是 是 是否可用于高级数据分析 不可以 可以 可以 不可以 可以 是否需要安装软件或者其他插件 需要,需要安装 RMagick,ImageMagick 和 Gruff 需要,JDK 1.3 版或更高 不需要 不需要 不需要 能否生成动态图表 不能 是否支持输出到图片 支持 支持 支持 不支持 支持 UTF8 支持 文档未提及 易用性 易用,但是需要写很多代码 并不易用。对用户较友好 很复杂,太多用于配置图表的 xml 标记 非常易用,开发者和用户都可以轻易上手 非常易用,开发者和用户都可以轻易上手 2D/3D 条形图支持 折线图支持 散点图支持 面状图支持 2D/3D 饼图支持 2D/3D 环状图支持 是,以环形图形式 甘特图支持 是(FusionWidgets v3 的一部分) 混合图支持 仪表图支持 是(XML/SWF 标准的一部分) 是(FusionWidgets v3 的一部分) 实时图支持 是(FusionWidgets v3 的一部分) 数据驱动地图 是(FusionWidgets v3 的一部分)本文中,我们将会研究如何使用 FusionCharts 和 MySQL 在 Rails 中绘制图表。FusionCharts 是一个基于 Flash 的图表生成组件,它能够帮助开发者创建可交互的动态图表。同样,它也可以和任何一种 Web 脚本语言绑定,以最少的代码绘制出优秀的图表。不仅如此,FusionCharts 甚至可以封装成模块并在 RoR 中使用。易于使用、多种图表类型支持、优秀的文档以及良好的支持是本文我们介绍 FusionCharts 的原因。

这篇文章以一个应用程序为例,描述了在 RoR 下 FusionCharts 生成图表的机制。这个应用完整运行所需要的软件有:

• FusionCharts 免费版 / v3:

FusionCharts 免费版可以从 www.fusioncharts.com/free 下载。而功能更全面的商业版可以从 www.fusioncharts.com 上下载。在本文中,我们使用的是免费版。

FusionCharts 的安装需要将安装包中的 SWF 和.rb 文件拷贝到合适的位置。.rb 文件是在 Download Package > Code > RoR > Libraries 目录下。

• Ruby 1.8.6 或更高版本:

下载地址是 http://www.rubyonrails.org/down

• Rails gem 2.0.2 或更高版本:

在 RubyGems 加载之后,如果要完整安装 Rails 以及其依赖包,你可以输入如下命令:

gem install rails

Rails 也可以从此页面下载。

• MySQL 4.0 或者更高版本:

MySQL 可以从此处下载。

这里我们以一个计时器为例。这个程序是为员工设计的,员工需要填写每周的上班时间,并且可以查看自己的工时表。本文将会从两个部分来讨论这个应用程序。第一个部分将处理开发上的问题,包括列举、编辑、展示和删除雇员以及工时表。如果你已经有一个需要集成图表的应用程序,你可以跳过这部分,然后直接进入下一个部分,下个部分将会阐述如何将图表和应用程序集成在一起。本文假设读者有基本的 Ruby on Rails 的知识。

创建基本的计时器程序

在脚手架框架(scaffolding framework)的帮助下,一些基本功能,例如列举、编辑、展示和删除雇员以及时间表,可以很简单地生成出来。生成基本的员工和时间表控制器的命令如下:(运行第一个命令后,在创建的 TimeTrackerApplication 目录下运行后面两个命令)

复制代码
rails –d mysql TimeTrackerApplication
ruby script/generate scaffold Employee name:text
ruby script/generate scaffold Timesheet log_date:datetime hours_spent:integer employee_id:integer

下一步,你需要修改 config 文件夹里面的 database.yml,让其指向“timetrackerdb”,并且配置好用户名和密码。运行如下命令创建数据库:

复制代码
rake db:create
rake db:migrate

在 mysql 中运行如下命令,创建 employees 和 timetables 表的外键。

复制代码
alter table timesheets add constraint fk_employee_id foreign key fk_employee_id(employee_id) references employees(id) on delete cascade

当然,创建外键的方法有多种;不过如果要深入下去,那么就超出了本文的讨论范围。你需要在模型之间创建关联才能够在 Ruby on Rails 中表示外键。

在 Employee 模型中,在类声明语句后,加入如下语句:

复制代码
has_many :timesheets

而在 Timesheet 模型你需要加入:

复制代码
belongs_to :employee

运行 sql 脚本 db/sampledata.sql 将样例数据插入到数据库中。至此,基本的程序和数据已经就绪,你可以增加、查看、编辑和删除雇员。

在应用程序中集成图表

当程序就绪之后,下面我将介绍如何生成一名员工的工作时间图表:

• 将 FusionCharts 文件夹(Download Package > Code > FusionCharts)拷贝到 TimeTrackerApplication 的public目录下。

• 将Download Package > Code > FusionCharts 文件夹中的FusionCharts.js 拷贝到public/javascripts文件夹下。

• 将Download Package > Code > RoR > Libraries文件夹中的 fusioncharts_helper.rb 拷贝到 TimeTrackerApplication 的lib目录下。

至此,FusionCharts 的安装就已经完成了。

员工名单页中需要一个指向 Time Tracker Chart 的链接。这样,每个雇员都可以查看自己的工时图表。链接是在 app/views/employees/index.html.erb 文件中创建。列表 1 详细描述了链接创建的方法。这段代码是把这个链接加到此页面的其他链接之后。

列表 1

复制代码
<td><%= link_to 'Time Chart', {:action=>'view_timesheet_chart',:id=>employee.id} %></td>

图 1 展示的是员工名单页面。在设置完数据库之后,开发者使用 Ruby 脚手架框架,可以很容易地实现这个功能。我们可以访问“ http://yourserver :port/employees”来查看此页面。图 1 是屏幕部分截图。

图 1

点击“Time Chart”链接将会调用 employees 控制器的 view_timesheet_chart 动作。列表 2 列出了它的代码。这个动作的作用是展示选中员工的工时表。它会向 Employee 模型查询指定员工在“2008-12-01”至“2008-12-07”这段时间的工时表,得到结果之后,渲染“view_timelog_chart.html.erb”文件。为了简单起见,在本文中,这个时间范围是固定的。当然,现实世界中,这个时间范围应该是可由员工指定。

列表 2

EmployeesController

复制代码
def view_timesheet_chart
start_date= "2008-12-01"
end_date="2008-12-07"
@employee_id = params[:id]
employee_details_with_timesheets = Employee.find_with_timesheets_in_date_range(@employee_id,start_date,end_date)
if(!employee_details_with_timesheets.nil?)
@employee_details_with_timesheets =employee_details_with_timesheets[0]
else
@employee_details_with_timesheets =nil;
end
headers["content-type"]="text/html"
end

这个动作以员工 id 为参数,它向 Employee 模型查询指定员工在特定时间范围内的工时表。我们将在 Employee 模型中加入如列表 3 所示的函数:

列表 3

Employee.rb

复制代码
def self.find_with_timesheets_in_date_range(id, start_date, end_date)
conditions="employees.id =? and log_date between ? and ?"
employee_details_with_timesheets=self.find(:all, :include=>'timesheets', :conditions=> [conditions,id,start_date,end_date], :order=>'log_date asc')
return employee_details_with_timesheets
end

最后,这个动作会渲染“view_time_chart.html.erb”文件。“view_time_chart.html.erb”模板使用的布局模板是“employee.html.erb”,所有 employees 控制器的视图都会采用这个布局模板。

列表 4

view_timesheet_chart.html.erb (在 app/views/employees 文件夹中)

复制代码
<%= javascript_include_tag "FusionCharts"%>
<%
#xml 文件内容以字符串的形式从模板生成器中得到
str_xml = render "employees/timesheet_data"
#创建图表 - 3D 柱状图,它的数据来自于 strXML
<b>render_chart '/FusionCharts/Column3D.swf' , '' , str_xml , 'TimeChart' , 650 </b>, <b> 400 </b>, <b> false </b>, <b> false do </b>-%>
<% <b> end </b>-%>

从上面的代码,我们知道了如何在视图页面中渲染图表:

  1. 引入 FusionCharts.js 文件。
  2. 从生成器中获取 xml 数据.(生成器的数据来源是控制器)
  3. 使用合适的参数调用render_chart函数渲染图表,

通常情况下,图表会以甘特图的形式表示,当然 FusionCharts 也支持这种形式。在此,简单起见,我们使用了柱状图。

第二步和 XML 的生成有关。FusionCharts 使用 XML(扩展标记语言)创建和操作图表。整个 FusionCharts 图表都是由 XML 控制。例如,你可以使用 XML 定义图表的外观,也可以定义图表的功能。每种图表都有大量特性可供选择。FusionCharts 也有自己的 XML 结构。现在讨论的图表是单系列图表(只有一个数据集),表示员工每周工作的天数和每天工作的时间。列表 5 是这个图表可以使用的一个 XML 例子。

列表 5

单系列图表 XML 样例

复制代码
<graph xAxisName="Day" showValues="1" caption="Time Tracker Chart" numberSuffix=" hrs." subcaption="For Employee John Wilson" yAxisName="Hours Spent">
<set name="Monday" value="8" color="AFD8F8"/>
<set name="Tuesday" value="6" color="F6BD0F"/>
<set name="Wednesday" value="5" color="8BBA00"/>
<set name="Thursday" value="9" color="A66EDD"/>
<set name="Friday" value="9" color="F984A1"/>
<set name="Saturday" value="8" color="CCCC00"/>
</graph>

要用现有的数据生成和列表 5 类似的 xml 文件,那么就需要用到生成器。

生成器是如何生成图表 XML 的呢?它会用到控制器动作中的 @employee_details_with_timesheets变量来构建出图表 XML。列表 6 展示的是这个生成器的实现。

列表 6

timesheet_data.builder (在 app/views/employees 文件夹中)

复制代码
xml = Builder::XmlMarkup.new(:indent=>0)
options = {
:caption=>'Time Tracker Chart',
:subcaption=>'For Employee '+ @employee_details_with_timesheets.name ,
:yAxisName=>'Hours Spent', :xAxisName=>'Day',
:showValues=>'1',
:formatNumberScale=>'0',
:numberSuffix=>' hrs.'
}
xml.graph(options) do
for timesheet in @employee_details_with_timesheets.timesheets do
log_day = timesheet.log_date.strftime('%a')
xml.set(
:name=>log_day,
:value=>timesheet.hours_spent,
:color=>''+get_FC_color)
end
end

在生成器中,你首先要创建一个 XMLMarkup 对象,将其“indent”属性赋值为 0,然后可以开始使用这个对象来构建 XML 了。

配置图表的所有选项都被放到了一个名为 options 的散列表中。如果希望了解更多 options 的信息,可以参考完整的 FusionCharts 文档。XML 文件的 root 元素是“graph”,其子节点是“set”,一个“set”节点表示一个特定员工的工时表。每一个“set”元素都有 name 和 value 属性。name 字段表示一周的第几天,而 value 字段表示的是在这一天中,当前员工的工作小时数。生成器使用控制器动作中的@employee_details_with_timesheets变量来存储这些值。

最后,在视图页中,render_chart 函数将会渲染出图表。这个函数的参数是 swf 图表名称、url、width、height、debugMode 和 registerWithJS。它可以在 lib 文件夹的 fusioncharts_helper 模块中找到。正如列表 7 所示,引入 application_helper.rb 之后,就可以在所有的视图中使用这个函数。

列表 7

application_helper.rb

复制代码
require 'fusioncharts_helper'include FusionChartsHelper

展示图表的 swf 文件在 public/FusionCharts 文件夹中。这里我们已经使用了 Column3D.swf 这个文件名,但是也可以生成任意名字的其他任何单系列的图表。而且,数据不仅仅可以从 dataXML 方法得到,也可以从 dataURL 中获取。这种用法在 FusionCharts 的文档中有举例。

现在,在员工列表页面中点击一个员工的“Time Chart”链接,从 01/12/2008 到 07/12/2008 这一周的工作时间将会以图表的形式展现出来。就像图 2 一样。

图 2

如何生成图表概述:

设置完 FusionCharts,并且引入了 application_helper.rb 中的 FusionChartsHelper 之后,按照如下步骤生成图表:

  1. 控制器动作负责从数据库中寻找所需数据。
  2. 根据当前数据编写生成器。
  3. 在第一步提到的控制器动作所绑定的视图中,开发者有两种方式从生成器中取得 XML,一种是直接将数据传递给生成器,或者让生成器从控制器动作中获取数据。
  4. 下一步,使用合理的参数(包括从第三步中得到的 XML)调用 render_chart 函数。

通过一个计时器的讲解,你已经学到了如何在 Ruby on Rails 中使用 FusionCharts 创建简单的图表。而且,只要对这个程序进行简单的修改,你就能得到一个所有员工的工时图表。或者,你甚至可以深入下去,绘制出某个特定员工的详细工时表。当然,你也可以使用 Ajax 来获取图表。诸如此类的改进数不胜数。FusionCharts 的下载包中就包含了很多值得深入研究的例子。本文讲解的应用程序可以从这里下载。

关于作者:

本文作者有着六年的IT 咨询从业经验,并且对大量的Web 技术感兴趣,包括J2EE 栈、Ruby on Rails 和PHP。

查看英文原文 Amazing Charts In Rails


感谢李明对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2010-06-07 22:485351
用户头像

发布了 90 篇内容, 共 36.7 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

YashanDB|yasboot 执行 cluster status 命令失败的处理办法

数据库砖家

数据库

虚拟机中的 YashanDB 无法从本机访问的处理办法

数据库砖家

数据库

使用 Druid 查询 GIS 空间数据时报 read time out 的排查与规避方法

数据库砖家

数据库

RocketMQ高级使用

量贩潮汐·WholesaleTide

RocketMQ

从被动响应到主动预防:AI驱动下的运维流程革命

嘉为蓝鲸

AIOPS 智能运维 DeepSeek

时序数据库 TimechoDB v2.0.3 发布 | 支持元数据导入导出脚本适配表模型等功能

Apache IoTDB

【ITSM运营】问题管理全景图:从识别到复盘的闭环优化体系

嘉为蓝鲸

AIOPS ITSM 智能运维

如何在 YashanDB 备机上安全进行备份与恢复操作

数据库砖家

数据库

一键多环境构建——用 Hvigor 玩转 HarmonyOS Next

鸿蒙魔法师

鸿蒙 HarmonyOS HarmonyOS NEXT Harmony5

YashanDB 使用 imp 导入时报 YAS-08023 的原因与处理办法

数据库砖家

数据库

想要给软件加点功能啥的,源码是必须要有的

程序员郭顺发

天润融通重磅亮相AWS香港峰会,阐述“业务专家 + AI员工”新模式

天润融通

Timer-XL 时序大模型论文入选 ICLR 2025,通用与时序场景性能均达到领先水平

Apache IoTDB

Hive 初始化 YashanDB 报错 YAS-04209 的原因与处理办法

数据库砖家

数据库

Python 查询 GBK 编码的 YashanDB CLOB 字段数据被截断的原因与修复

数据库砖家

数据库

SD-WAN怎么实现企业海外网络访问?

Ogcloud

SD-WAN 企业组网 海外网络加速 海外网络访问 海外网络连接

深入解析金仓数据库的模式:创建、管理与应用

金仓技术

KingBase 金仓数据库

YashanDB 收集统计信息时报 YAS-00507 错误的处理方法

数据库砖家

数据库

YashanDB|启动 yasom 报错 sqlite connection error 的处理思路

数据库砖家

数据库

YashanDB 安装时报 SSH 认证失败错误的处理方法

数据库砖家

数据库

AARRR模型是什么,包括哪些阶段?一文弄懂PM必备的思维模型!

职场工具箱

人工智能 产品 AI 产品经理 AIGC

使用 JDBC 批量插入 YashanDB GIS 空间数据的示例

数据库砖家

数据库

通过 JDBC 向 YashanDB 批量插入空间数据的标准写法

数据库砖家

数据库

金贝旗舰级新品闪光灯亮相PE展,首日体验者络绎不绝

科技热闻

埃文科技大模型领域研究再获突破!两篇创新论文入选国际顶会KDD 2025

郑州埃文科技

大模型

告别传统运维繁琐:OpsPilot 对话式交互让 K8s 集群管理更轻松

嘉为蓝鲸

k8s 智能运维 #WeOps OpsPilot

YashanDB|yasql 使用 as sysdba 登录失败的排查思路

数据库砖家

数据库

YashanDB 登录报 YAS-02143:密码中含特殊字符的处理方法

数据库砖家

数据库

YashanDB 使用 listagg 报 YAS-02511 的原因及解决方案

数据库砖家

数据库

详解中间件

量贩潮汐·WholesaleTide

中间件 js

跨国视频会议总断线?教你这3个实用方法

Ogcloud

跨国网络 跨国网络专线 国际网络 跨国视频会议

Rails中精彩的图表_Ruby_Srividya Sharma_InfoQ精选文章