Agile Web Development with Rails 翻译(二十六)
Agile Web Development with Rails 翻译(二十六)
混合大小写,下划线和复数
我们经常使用短语来命名变量和类。在Ruby里通常约定变量的名字全是小字母,单词之间用下划线隔开。类和模块命名则不同:它们没有下划线,短语中每个单词的第一个字母以大写开头。(我们称这是混合大小写)。这些约定会这样命名变量,比如order_status,和类名字如LineItem。
Rails中采用了这种约定并以两种方式进行了扩展。首先,它假定数据库的表名和变量名一样,都是小写字母,单词之间是下划线。Rails还假定表名总是复数形式。比如表名orders,third_parties。
另一方面Rails假定文件以带有下划线的小写字母命名。
Rails使用这些命名约定来自动转换名字。例如,你的应用程序可能包含一个model类,它用来来处理商品项目。你已经使用Ruby的命名约定来定义这个类,叫LineItem。通过这个名字,Rails将自动推论出以下的规则:
1、对应的数据库表名被称为line_items。这是类名字,被转换成小写字母,并在单词和复数之间使用了下划线。
2、Rails也将知道在一个叫line_item.rb(在app/models目录中)的文件中去寻找类LineItem的定义。
Rails的controller也有额外的命名约定。如果我们的应用程序由一个storecontroller,那么会发生以下一些情形:
1、Rails假定类被称为StoreController,并且它是定义在app/controllers目录下store_controller.rb的文件中。
2、它也假设有个名为StoreHelper的helper模块,它是位于app/helpers目录下的store_helper.rb中。
3、它缺省地接受负责输出的views和layout template包含在目录app/views/layouts/下的store.rhtml或者store.rxml中。
所有约定显示在图13.3中。
还有些要注意。通常情况下,Ruby代码中引用以上那些文件中的class和module必须使用require来包括ruby的源文件。因为Rails知道这些文件名,类名之间的关系。所以require语句在Rails里是没有必要的。相反,当你第一次引用Rails不知道的类或模块时,Rails使用命名约定来转换类名字为文件名,并试图在幕后加载这个文件。这样的好处是不言而喻的,你可以直接引用model类名,这个model将自动加载到你的应用程序中。
正如你所看到的,这种模式在你的类被存储到sessions中时会行不通。因此你必须要明确地声明。即使这样,你也不必使用require。相反,你的控制器只要包含一行,像这样:
class StoreController < ApplicationController
model :line_item
# ...
注意这里的命名约定是如何做到一致的。符号:line_time是带有下划线的小写。它将会把line_item.rb加载进来,这个文件包含类LineItem。
分组 Controller 到模块中
到目前为止,我们所有的controller都是在app/controllers目录中。有时加入更多的结构会更方便。例如:我们的store可能会用到很多的controller,它是要执行相关的管理上的功能。为了不影响到上层的名字空间,我们可能会把他们归组到一个单独的admin名字空间。
-------------------------------------------------
David 说. . .
为什么表要用复数?
因为听起来好理解。实际上,“从products选择一个 Product 。”就好像是“Order has_many :line_items” 。目的是连接程序和会话,这通过创建两者共享的domain语言来实现。Having such a language means cutting down on the mental translation that otherwise confuses the discussion of a product description with the client when it’s really implemented as merchandise body. These communications gaps are bound
to lead to errors.
Rails sweetens the deal by giving you most of the configuration for free if you follow the standard conventions. Developers are thus rewarded for doing the right thing, so it’s less about giving up “your ways” and more about getting productivity for free.
----------------------------------------------------------------------
rails将会使用一个简单的约定来做这件事。如果引入的请求有一个名为admin/book的controller,Rails将到目录app/controllers/admin中找名为book_controller的controller。也就是说,这个controller的名字的最后部分将被解析到一个名为name_controller.rb的文件,并且前导路径信息将被用于子目录的导航。
想像我们的应用程序有两组controller(admin/xxx和content/xxx),并且两者被分组定义到一个book controller中。称为book_controller.rb的文件被放在app/controllers下的admin和content子目录中。这两个controller文件将被定义在类名为BookController的类中。如果Rails不进一步处理,这两个类会冲突。
To deal with this, Rails assumes that controllers in subdirectories of the directory app/controllers are in Ruby modules named after the subdirectory. 那么,admin子目录内的book controller将被声明为
class Admin::BookController < ApplicationController
# ...
end
content子目录内的book controller将在Content模块内。
class Content::BookController < ApplicationController
# ...
end
这样两个controller就被在你的应用程序中分离开来。
用于这些controller的模板出现在app/views子目录中。那么,view模板就对应于请求 http://my.app/admin/book/edit/1234
它在在同文件中。
app/views/admin/book/edit.rhtml
你会高兴地知道,controller generator 理解模块内的controller的概念,并且让你用如下命令行创建它们。比如,
myapp> ruby script/generate controller Admin::Book action1 action2 ...
这种controller命名模式有个分支,在我们启动URL来连接动作时。我们在287页讨论它。
13.5 Active Support
Active Support 是由所有Rails组件共享的一套库。大多数用于Rails内部。但是,Active Support也扩展了一些Ruby的内建类。本节,我们将快速地列出这些扩展的大多数部分。
扩展Numbers
类 Fixnum 获得了两个实例方法even? 和 odd? 。
所有数字对象获得了一套缩放方法。
puts 20.bytes #=> 20
puts 20.kilobytes #=> 20480
puts 20.megabytes #=> 20971520
puts 20.gigabytes #=> 21474836480
puts 20.terabytes #=> 21990232555520
还有基于时间的缩放方法。这些转换它们的被调到等同的秒中。Months()和years()方法是大致的—月数是30天,年的天数是365天。
puts 20.minutes #=> 1200
puts 20.hours #=> 72000
puts 20.days #=> 1728000
puts 20.weeks #=> 12096000
puts 20.fortnights #=> 24192000
puts 20.months #=> 51840000
puts 20.years #=> 630720000
你也可以使用方法ago()和from_now()(或者它们的别名方法until()和since())计算相对于Time.now的时间。
puts Time.now #=> Tue May 10 17:03:43 CDT 2005
puts 20.minutes.ago #=> Tue May 10 16:43:43 CDT 2005
puts 20.hours.from_now #=> Wed May 11 13:03:43 CDT 2005
puts 20.weeks.from_now #=> Tue Sep 27 17:03:43 CDT 2005
puts 20.months.ago #=> Thu Sep 18 17:03:43 CDT 2003
时间扩展
Time 类获得了一组有用的方法,帮助你计算有关的时间。
now = Time.now
puts now #=> Tue May 10 17:15:59 CDT 2005
puts now.ago(3600) #=> Tue May 10 16:15:59 CDT 2005
puts now.at_beginning_of_day #=> Tue May 10 00:00:00 CDT 2005
puts now.at_beginning_of_month #=> Sun May 01 00:00:00 CDT 2005
puts now.at_beginning_of_week #=> Mon May 09 00:00:00 CDT 2005
puts now.at_beginning_of_year #=> Sat Jan 01 00:00:00 CST 2005
puts now.at_midnight #=> Tue May 10 00:00:00 CDT 2005
puts now.change(:hour => 13) #=> Tue May 10 13:00:00 CDT 2005
puts now.last_month #=> Sun Apr 10 17:15:59 CDT 2005
puts now.last_year #=> Mon May 10 17:15:59 CDT 2004
puts now.midnight #=> Tue May 10 00:00:00 CDT 2005
puts now.monday #=> Mon May 09 00:00:00 CDT 2005
puts now.months_ago(2) #=> Thu Mar 10 17:15:59 CST 2005
puts now.months_since(2) #=> Sun Jul 10 17:15:59 CDT 2005
puts now.next_week #=> Mon May 16 00:00:00 CDT 2005
puts now.next_year #=> Wed May 10 17:15:59 CDT 2006
puts now.seconds_since_midnight #=> 62159.215938
puts now.since(7200) #=> Tue May 10 19:15:59 CDT 2005
puts now.tomorrow #=> Wed May 11 17:15:59 CDT 2005
puts now.years_ago(2) #=> Sat May 10 17:15:59 CDT 2003
puts now.years_since(2) #=> Thu May 10 17:15:59 CDT 2007
puts now.yesterday #=> Mon May 09 17:15:59 CDT 2005
Active Support也包括一个TimeZone类。TimeZone对象包装时区的名字和时差。该类包含了世界时区的列表。更多细节可查看Active Support RDoc文档。
字符串扩展
Active Support 给所有字符串添加了些方法以支持Rails将名字从单数转换为复数,小写变成混合大小写等等。通常一般的应用程序只用到两个。
puts "cat".pluralize #=> cats
puts "cats".pluralize #=> cats
puts "erratum".pluralize #=> errata
puts "cats".singularize #=> cat
puts "errata".singularize #=> erratum
13.6 Logging in Rails
Rails已经把日志机制内建到框架中。为了得到更加精细的日志,Rails让Logger对象在Rails应用程序的所有代码都是可见的。
Logger是一个简单的日志框架,它已经包装进Ruby的最新版本。(在命令行上输入 ri Logger你可得到更多信息。)对于我们来说,只需知道能生成几类日志信息,包括warning,info,error,fatal级别的信息,就足够了。
logger.warn("I don't think that's a good idea")
logger.info("Dave's trying to do something bad")
logger.error("Now he's gone and broken it")
logger.fatal("I give up")
在Rails应用程序中,这些信息将会写入log目录中的相应环境的文件。这些文件的使用依赖于你应用程序运行的环境。开发的应用程序将日志到log/development.log中,测试中将日志到test.log中,发行后日志到production.log中。
13.7 Debugging Hints
首先想到的和广泛使用的是,写测试代码!rails使得写unit test和functional test变得容易。使用了它们,你将发现bug的出现率会显著减少。测试是廉价的保单。
测试会告诉你哪些东西起作用,哪些不起作用,有助于你隔离有问题的代码。但有时,出现问题的原因不是非常明显。
如果问题出现在一个model中,你可能想在web程序外来跟踪相关的类。script/console把你的rails程序带到irb的会话中,让你有机会测试方法。下面是当我们使用控制台来更新一个产品的单价时的会话。
depot> ruby script/console
Loading development environment.
irb(main):001:0> pr = Product.find(:first)
=> #<Product:0x248acd0 @attributes={"image_url"=>"/images/sk..."
irb(main):002:0> pr.price
=> 29.95
irb(main):003:0> pr.price = 34.95
=> 34.95
irb(main):004:0> pr.save
=> true
日志和跟踪是动态理解复杂的应用程序的最好方式。你会发现development的日志文件中有很多信息。当不希望的事情发生时,它或许是你想看第一个地方。它也写入web服务日志。如果你在开发环境中使用了WEBric的话,这将在使用script/server命令的窗口滚动。
你也可以添加你自已的信息到前面描述的Logger对象中。有时候日志文件很忙,它很难找到你添加信息。在这些情况下,如果你使用WEBrick,的话将你出现WEBrick控制台上信息写入到STDERR中。
如果一个页面显示警告信息,你可能想转储对象。Debug() helper方法可用于这种情况。它格式化对象并确保其内容是有效的HTML。
<h3>Your Order</h3>
<%= debug(@order) %>
<div id="ordersummary">
. . .
</div>
最后,所有问题都似乎得不到修正,你可以在你运行应用程序时,使用调试器。通常这只能在开发环境下有效。
要使用断点:
1、在你想停下之处插入方法breakpoint( )。你可以像这个方法传递一个字符串—想区别的信息。
2、在控制台上,导航你应用程序的基本目录和命令入口。
depot> ruby script/breakpointer
No connection to breakpoint service at
druby://localhost:42531 (DRb::DRbConnError)
Tries to connect will be made every 2 seconds...
不要为没有连接消息烦恼—它只意味着你的断言并没有被击中。
3、Using a browser, prod your application to make it hit the breakpoint( ) method. When it does, the console where breakpointer is running will burst into life—you’ll be in an irb session, talking to your running web application. You can inspect variables, set values, add other breakpoints, and generally have a good time. When you quit irb, your application will continue running.
By default, breakpoint support uses a local network connection to talk between your application and the breakpointer client. You might be able to use the -s option when you run breakpointer to connect to an application on another machine.
13.8 What’s Next
If you’re looking for information on Active Record, Rails’ object-relational mapping layer, you need the next two chapters. The first of these covers the basics, and the second gets into some of the more esoteric stuff. They’re long chapters—Active Record is the largest component of Rails.
Chapter 16, Action Controller and Rails, looks at Action Controller, the brains behind Rails applications. This is where requests are handled and business logic lives. After that, Chapter 17, Action View, describes how you get from application-level data to browser pages.
But wait (as they say), there’s more! The new style of web-based application makes use of JavaScript and XMLHttpRequest to provide a far more interactive user experience. Chapter 18, The Web, V2.0, tells you how to spice up your applications.
Rails can do more than talk to browsers. Chapter 19, Action Mailer, shows you how to send and receive e-mail from a Rails application, and Chapter 20, Web Services on Rails, on page 411, describes how you can let others access your application programmatically using SOAP and XMLRPC.
We leave two of the most important chapters to the end. Chapter 21, Securing Your Rails Application, contains vital information if you want to be able to sleep at night after you expose your application to the big, bad world. And Chapter 22, Deployment and Scaling, contains all the nittygritty details of putting a Rails application into production and scaling it as your user base grows.

浙公网安备 33010602011771号