产品战略专家梁宁确认出席AICon北京站,分享AI时代下的商业逻辑与产品需求 了解详情
写点什么

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:485049
用户头像

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

关注

评论

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

2021大厂Java社招最全面试题,2021Java面经

Java 面试 后端

个推0代码数据可视化实操:基于Tableau的中国奥运数据探索

个推

2021年Android岗位BAT大厂面试题知识点小结,阿里巴巴安卓面试题答案

android 面试 移动开发

三维可视化数字能源系统,助力智慧园区高效能源管理

ThingJS数字孪生引擎

大前端 物联网 可视化 数字孪生

2021Java高级进阶学习资料,StringBoot编程式事务与声明式事务

Java 面试 后端

2021年Android大厂面试,劲爆

android 面试 移动开发

2021互联网大厂Java面经合集,阿里面试官必问

Java 面试 后端

2021Java者未来的出路在哪里,怒斩获了30家互联网公司offer

Java 面试 后端

Jenkins: 重置管理员密码

吴脑的键客

jenkins

2021Java进阶者的新篇章,做了5年Java

Java 面试 后端

2021年Android工作或更难找,透彻分析源码

android 面试 移动开发

2021年Android常见面试题目,程序员必须要了解的知识点

android 移动开发 Android面试

硬实力再获认可!焱融科技入选《2021爱分析云计算厂商全景报告》

焱融科技

云计算 分布式 高性能 文件存储 科技

阿里淘技术带佬新作:设计模式的完美演绎,共计1290页

Java 程序员 架构 面试 计算机

2021Java高频精选面试题讲解,2021Java大厂面试真题

Java 面试 后端

2021一位Java中级程序员的跳槽面经,springmvc源码解析pdf

Java 面试 后端

M-SQL:超强的多任务表示学习方法

华为云开发者联盟

sql 自然语言 M-SQL SQL语句 多任务

2021华为Java高级面试题及答案,Java技术成长

Java 面试 后端

2021年Android工作或更难找,深入剖析原理

android 面试 移动开发

2021大厂Java春招面试经历,Java高级架构视频

Java 面试 后端

直播回顾 | seL4基金会主席谈物理系统安全工程实践

鉴释

自动驾驶 操作系统 微内核 在线研讨会

2021年Android大厂面试,送大厂面经一份

android 面试 移动开发

2021京东最新Java面试真题解析,2021Java开发面试解答

Java 面试 后端

2021年Android常见面试题,Android培训那里好

android 面试 移动开发

分布式服务下,消息中间件改造

Java 架构 面试 分布式 后端

2021年Android工作或更难找,2021Android面经

android 移动开发

2021大厂Java开发面试总结+解答,21条MySQL性能调优经验

Java 面试 后端

2021大厂Java春招面试经历,宅家36天咸鱼翻身入职腾讯

Java 面试 后端

2021年Android开发前景如何,腾讯T2大牛亲自讲解

android 面试 移动开发

2021Java面试心得,Spring的XML解析原理

Java 面试 后端

2021Java面试心得,淘汰机制、缓存雪崩

Java 后端

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