Ruby on Rails 3.1 Release Notes

Ruby on Rails 3.1 Release Notes

Highlights in Rails 3.1:


  • Streaming
  • Reversible Migrations 可逆(数据)迁移
  • Assets Pipeline Assets管道
  • jQuery as the default JavaScript library jQuery作为默认的 JavaScript library

This release notes cover the major changes, but don’t include every little bug fix and change. If you want to see everything, check out the listofcommits in the main Rails repository on GitHub.

这次发行notes涵盖了主要的changes,但是没有包含每个很littlebug修复和chage。如果你希望看到所有的事情,检查Rails GitHub主代码仓库中的listofcommits

1 Upgrading to Rails 3.1升级到Rails 3.1

If you’re upgrading an existing application, it’s a great idea to have good test coverage before going in. You should also first upgrade to Rails 3 in case you haven’t and make sure your application still runs as expected before attempting to update to Rails 3.1. Then take heed of the following changes:

如果你打算升级一个存在的应用程序,在开始进入升级的时候有一个很好的测试覆盖是一个好主意。你还应该首先升级到Rails 3以防止你并没有确保你的应用程序在企图升级到Rails 3.1之前能够预计到升级后仍然能够运行。然后留意随后(介绍)的changes

1.1 Rails 3.1 requires at least Ruby 1.8.7

Rails 3.1 requires Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible. Rails 3.1 is also compatible with Ruby 1.9.2.

Rails 3.1需要至少Ruby 1.8.7或者更高。曾经支持的所有的早先的Ruby版本被正式取消,你需要尽快升级。Rails 3.1同时也与Ruby 1.9.2兼容。

Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults, so if you want to use 1.9.x jump on 1.9.2 for smooth sailing.

注意Ruby 1.8.7 p248p249marshaling bugs其与Rails冲突。Ruby企业版自1.8.7-2010.02 发行版已经修复了这些bug。在以1.9开头的rubyRuby 1.9.1是不可用的因为it outright segfaults,因此如果你想使用1.9.x可以平稳的跳至1.9.2

2 Creating a Rails 3.1 application

# You should have the ‘rails’ rubygem installed

$ rails new myapp

$ cd myapp

2.1 Vendoring Gems

Rails now uses a Gemfile in the application root to determine the gems you require for your application to start. This Gemfile is processed by the Bundler gem, which then installs all your dependencies. It can even install all the dependencies locally to your application so that it doesn’t depend on the system gems.

Rails现在使用一个位于应用程序根目录的Gemfile文件来决定使你开始你的应用程序的require。这个Gemfile文件被Bundler gem加工生成,它会随后安装你所有的依赖。它甚至可以以你的应用程序为locally安装依赖,使得你的应用程序不用依赖系统gems


vendor/ A place for all third-party code. In a typical Rails application, this includes Ruby Gems, the Rails source code (if you install it into your project) and plugins containing additional prepackaged functionality.放置第三方代码的地方。在一个典型的Rails应用程序中,这里包含Ruby GemsRails源代码(如果你把Rails安装到你的项目中)还包含一些预先包装好的额外的插件

More information: – bundlerhomepage

2.2 Living on the Edge

Bundler and Gemfile makes freezing your Rails application easy as pie with the new dedicated bundle command. If you want to bundle straight from the Git repository, you can pass the --edge flag:

BundlerGemfile通过新的专用bundle 命令来冻结你的应用程序就像吃馅饼一样简单。如果你想直接从Git仓库bundle,你可以通过edge flag

$ rails new myapp –edge

If you have a local checkout of the Rails repository and want to generate an application using that, you can pass the --dev flag:

如果你有一个从Rails源代码仓库checkout的本地Rails并且你想生成一个应用程序使用(上面的方法)你可以通过dev 标志:

$ ruby /path/to/rails/bin/rails new myapp –dev

3 Rails Architectural建筑的Changes

3.1 Assets Pipeline

The major change in Rails 3.1 is the Assets Pipeline. It makes CSS and JavaScript first-class code citizens and enables proper organization, including use in plugins and engines.

Rails 3.1中主要的更改就是Assets Pipeline(管道)。它使得CSSJavaScript 一流的代码公民可以合适的组织他们,包含使用pluginisengines

The assets pipeline is powered by Sprockets and is covered in the AssetPipeline guide.

3.2 HTTP Streaming

HTTP Streaming is another change that is new in Rails 3.1. This lets the browser download your stylesheets and JavaScript files while the server is still generating the response. This requires Ruby 1.9.2, is opt-in and requires support from the web server as well, but the popular combo of nginx and unicorn is ready to take advantage of it.

HTTP StreamingRails 3.1另一更改。这使得浏览器下载你的stylesheetsJavaSript文件即使服务器仍然在响应。这需要Ruby 1.9.2,它是需要从服务器中选择以及服务器同样支持HTTP Streaming,但是受欢迎的nginxunicom组织已经准备advantage HTTP Streaming

3.3 Default JS library is now jQuery

jQuery is the default JavaScript library that ships with Rails 3.1. But if you use Prototype, it’s simple to switch.

Jquey是默认的JavaScript library搭载在Rrails 3.1.但是如果你使用Prototype,它更改很简单。

$ rails new myapp -j prototype

3.4 Identity Map 身份map

Active Record has an Identity Map in Rails 3.1. An identity map keeps previously instantiated records and returns the object associated with the record if accessed again. The identity map is created on a per-request basis and is flushed at request completion.

Rails 3.1Active Record有一个Indentity Map。一个identity map保留先前的实例化的记录并且如果再次访问返回记录的对象的关系。Indentity map是基于每个请求创建的并且在请求完成刷新。

Rails 3.1 comes with the identity map turned off by default.

Rails 3.1默认Identity map是关闭的。

4 Railties

  • jQuery is the new default JavaScript library.

Jquey是新的默认的JavaScript library

  • jQuery and Prototype are no longer vendored and is provided from now on by the jquery-rails and prototype-rails gems.

jQueyPrototype不再vendored并且从现在开始提供的是jquery-rails and prototype-rails gems

  • The application generator accepts an option -j which can be an arbitrary string. If passed “foo”, the gem “foo-rails” is added to the Gemfile, and the application JavaScript manifest requires “foo” and “foo_ujs”. Currently only “prototype-rails” and “jquery-rails” exist and provide those files via the asset pipeline.

应用程序创建器接受一个选项-j其可以是任意字符串。如果传递foo”gem “foo-rails”就被添加到Gemfile,并且应用程序的JavaScript manifest requires “foo” and “foo_ujs”。当前只有prototype-rails” and “jquery-rails”存在并且通过asset pipeline提供这些文件。

  • Generating an application or a plugin runs bundle install unless --skip-gemfile or --skip-bundle is specified.

生成一个应用程序或者一个plugin运行bundle install除非–skip-gemfile或者–skip-bundle被指定

  • The controller and resource generators will now automatically produce asset stubs (this can be turned off with --skip-assets). These stubs will use CoffeeScript and Sass, if those libraries are available.

Controllerresource创建器将会自动的产生asset stubs(this can be turned off with --skip-assets)。这些stub将会使用CoffeeScript and Sass,如果这些libraries是可用的。

  • Scaffold and app generators use the Ruby 1.9 style hash when running on Ruby 1.9. To generate old style hash, --old-style-hash can be passed.
  • Scaffold controller generator creates format block for JSON instead of XML.
  • Active Record logging is directed to STDOUT and shown inline in the console.
  • Added config.force_ssl configuration which loads Rack::SSL middleware and force all requests to be under HTTPS protocol.
  • Added rails plugin new command which generates a Rails plugin with gemspec, tests and a dummy application for testing.
  • Added Rack::Etag and Rack::ConditionalGet to the default middleware stack.
  • Added Rack::Cache to the default middleware stack.
  • Engines received a major update – You can mount them at any path, enable assets, run generators etc.

5 Action Pack

5.1 Action Controller

  • A warning is given out if the CSRF token authenticity cannot be verified.
  • Specify force_ssl in a controller to force the browser to transfer data via HTTPS protocol on that particular controller. To limit to specific actions, :only or :except can be used.
  • Sensitive query string parameters specified in config.filter_parameters will now be filtered out from the request paths in the log.
  • URL parameters which return nil for to_param are now removed from the query string.
  • Added ActionController::ParamsWrapper to wrap parameters into a nested hash, and will be turned on for JSON request in new applications by default. This can be customized in config/initializers/wrap_parameters.rb.
  • Added config.action_controller.include_all_helpers. By default helper :all is done in ActionController::Base, which includes all the helpers by default. Setting include_all_helpers to false will result in including only application_helper and the helper corresponding to controller (like foo_helper for foo_controller).
  • url_for and named url helpers now accept :subdomain and :domain as options.
  • Added Base.http_basic_authenticate_with to do simple http basic authentication with a single class method call.

class PostsController < ApplicationController

USER_NAME, PASSWORD = “dhh”, “secret”


before_filter :authenticate, :except => [ :index ]


def index

render :text => “Everyone can see me!”



def edit

render :text => “I’m only accessible if you know the password”




def authenticate

authenticate_or_request_with_http_basic do |user_name, password|

user_name == USER_NAME && password == PASSWORD




..can now be written as

class PostsController < ApplicationController

http_basic_authenticate_with :name => “dhh”, :password => “secret”, :except => :index


def index

render :text => “Everyone can see me!”



def edit

render :text => “I’m only accessible if you know the password”



Added streaming support, you can enable it with:

class PostsController < ActionController::Base



You can restrict限制it to some actions by using :only or :except. Please read the docs at ActionController::Streaming for more information.

  • The redirect route method now also accepts a hash of options which will only change the parts of the url in question, or an object which responds to call, allowing for redirects to be reused.

5.2 Action Dispatch

  • config.action_dispatch.x_sendfile_header now defaults to nil and config/environments/production.rb doesn’t set any particular value for it. This allows servers to set it through X-Sendfile-Type.
  • ActionDispatch::MiddlewareStack now uses composition组成over inheritance and is no longer an array.
  • Added ActionDispatch::Request.ignore_accept_header to ignore accept headers.
  • Added Rack::Cache to the default stack.
  • Moved etag responsibility from ActionDispatch::Response to the middleware stack.
  • Rely on Rack::Session stores API for more compatibility across the Ruby world. This is backwards incompatible since Rack::Session expects #get_session to accept four arguments and requires #destroy_session instead of simply #destroy.
  • Template lookup now searches further up in the inheritance chain.

5.3 Action View

  • Added an :authenticity_token option to form_tag for custom handling or to omit the token by passing :authenticity_token => false.
  • Created ActionView::Renderer and specified an API for ActionView::Context.
  • In place SafeBuffer mutation is prohibited禁止in Rails 3.1.
  • Added HTML5 button_tag helper.
  • file_field automatically adds :multipart => true to the enclosing form.
  • Added a convenience idiom to generate HTML5 data-* attributes in tag helpers from a :data hash of options:

tag(“div”, :data => {:name => ‘Stephen’, :city_state => %w(Chicago IL)})

# => <div data-name=”Stephen” data-city-state=”[&quot;Chicago&quot;,&quot;IL&quot;]” />

Keys are dasherized. Values are JSON-encoded, except for strings and symbols.

  • csrf_meta_tag is renamed to csrf_meta_tags and aliases csrf_meta_tag for backwards compatibility.
  • The old template handler API is deprecated and the new API simply requires a template handler to respond to call.
  • rhtml and rxml are finally removed as template handlers.
  • config.action_view.cache_template_loading is brought back which allows to decide whether templates should be cached or not.
  • The submit form helper does not generate an id “object_name_id” anymore.
  • Allows FormHelper#form_for to specify the :method as a direct option instead of through the :html hash. form_for(@post, remote: true, method: :delete) instead of form_for(@post, remote: true, html: { method: :delete }).
  • Provided JavaScriptHelper#j() as an alias for JavaScriptHelper#escape_javascript(). This supersedes the Object#j() method that the JSON gem adds within templates using the JavaScriptHelper.
  • Allows AM/PM format in datetime selectors.

6 Active Record

  • Added a class method pluralize_table_names to singularize/pluralize复数table names of individual models. Previously this could only be set globally for all models through ActiveRecord::Base.pluralize_table_names.

class User < ActiveRecord::Base

self.pluralize_table_names = false


  • Added block setting of attributes to singular associations. The block will get called after the instance is initialized

class User < ActiveRecord::Base

has_one :account



user.build_account{ |a| a.credit_limit => 100.0 }

  • Added ActiveRecord::Base.attribute_names to return a list of attribute names. This will return an empty array if the model is abstract or the table does not exist.
  • CSV Fixtures are deprecated and support will be removed in Rails 3.2.0.
  • ActiveRecord#new, ActiveRecord#create and ActiveRecord#update_attributes all accept a second hash as an option that allows you to specify which role to consider when assigning attributes. This is built on top of Active Model’s new mass assignment capabilities:

class Post < ActiveRecord::Base

attr_accessible :title

attr_accessible :title, :published_at, :as => :admin

end[:post], :as => :admin)

  • default_scope can now take a block, lambda, or any other object which responds to call for lazy evaluation.
  • Default scopes are now evaluated at the latest possible moment, to avoid problems where scopes would be created which would implicitly contain the default scope, which would then be impossible to get rid of via Model.unscoped.
  • PostgreSQL adapter only supports PostgreSQL version 8.2 and higher.
  • ConnectionManagement middleware is changed to clean up the connection pool after the rack body has been flushed.
  • Added an update_column method on Active Record. This new method updates a given attribute on an object, skipping validations and callbacks. It is recommended to use update_attribute unless you are sure you do not want to execute any callback, including the modification of the updated_at column. It should not be called on new records.
  • Associations with a :through option can now use any association as the through or source association, including other associations which have a :through option and has_and_belongs_to_many associations.
  • The configuration for the current database connection is now accessible via ActiveRecord::Base.connection_config.
  • limits and offsets are removed from COUNT queries unless both are supplied.

People.limit(1).count # => ‘SELECT COUNT(*) FROM people’

People.offset(1).count # => ‘SELECT COUNT(*) FROM people’

People.limit(1).offset(1).count # => ‘SELECT COUNT(*) FROM people LIMIT 1 OFFSET 1′

  • ActiveRecord::Associations::AssociationProxy has been split. There is now an Association class (and subclasses) which are responsible for operating on associations, and then a separate, thin wrapper called CollectionProxy, which proxies collection associations. This prevents namespace pollution, separates concerns, and will allow further refactorings.
  • Singular associations (has_one, belongs_to) no longer have a proxy and simply returns the associated record or nil. This means that you should not use undocumented methods such as bob.mother.create – use bob.create_mother instead.
  • Support the :dependent option on has_many :through associations. For historical and practical reasons, :delete_all is the default deletion strategy employed by association.delete(*records), despite the fact that the default strategy is :nullify for regular has_many. Also, this only works at all if the source reflection is a belongs_to. For other situations, you should directly modify the through association.
  • The behavior of association.destroy for has_and_belongs_to_many and has_many :through is changed. From now on, ‘destroy’ or ‘delete’ on an association will be taken to mean ‘get rid of the link’, not (necessarily) ‘get rid of the associated records’.
  • Previously, has_and_belongs_to_many.destroy(*records) would destroy the records themselves. It would not delete any records in the join table. Now, it deletes the records in the join table.
  • Previously, has_many_through.destroy(*records) would destroy the records themselves, and the records in the join table. [Note: This has not always been the case; previous version of Rails only deleted the records themselves.] Now, it destroys only the records in the join table.
  • Note that this change is backwards-incompatible to an extent, but there is unfortunately no way to ‘deprecate’ it before changing it. The change is being made in order to have consistency as to the meaning of ‘destroy’ or ‘delete’ across the different types of associations. If you wish to destroy the records themselves, you can do records.association.each(&:destroy).
  • Add :bulk => true option to change_table to make all the schema changes defined in a block using a single ALTER statement.

change_table(:users, :bulk => true) do |t|

t.string :company_name

t.change :birthdate, :datetime


  • Removed support for accessing attributes on a has_and_belongs_to_many join table. has_many :through needs to be used.
  • Added a create_association! method for has_one and belongs_to associations.
  • Migrations are now reversible可逆, meaning that Rails will figure out how to reverse your migrations. To use reversible migrations, just define the change method.

class MyMigration < ActiveRecord::Migration

def change

create_table(:horses) do

t.column :content, :text

t.column :remind_at, :datetime




  • Some things cannot be automatically reversed for you. If you know how to reverse those things, you should define up and down in your migration. If you define something in change that cannot be reversed, an IrreversibleMigration exception will be raised when going down.
  • Migrations now use instance methods rather than class methods:

class FooMigration < ActiveRecord::Migration

def up # Not self.up



  • Migration files generated from model and constructive migration generators (for example, add_name_to_users) use the reversible migrations change method instead of the ordinary up and down methods.
  • Removed support for interpolating插值string SQL conditions on associations. Instead, a proc should be used.

has_many :things, :conditions => ‘foo = #{bar}’ # before

has_many :things, :conditions => proc { “foo = #{bar}” } # after


Inside the proc, self is the object which is the owner of the association, unless you are eager loading the association, in which case self is the class which the association is within.

You can have any “normal” conditions inside the proc, so the following will work too:

has_many :things, :conditions => proc { ["foo = ?", bar] }


  • Previously :insert_sql and :delete_sql on has_and_belongs_to_many association allowed you to call ‘record’ to get the record being inserted or deleted. This is now passed as an argument to the proc.
  • Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePassword) to encapsulate dead-simple password usage with BCrypt encryption and salting.

# Schema: User(name:string, password_digest:string, password_salt:string)

class User < ActiveRecord::Base




  • When a model is generated add_index is added by default for belongs_to or references columns.
  • Setting the id of a belongs_to object will update the reference to the object.
  • ActiveRecord::Base#dup and ActiveRecord::Base#clone semantics语义have changed to closer match normal Ruby dup and clone semantics.
  • Calling ActiveRecord::Base#clone will result in a shallow copy of the record, including copying the frozen state. No callbacks will be called.
  • Calling ActiveRecord::Base#dup will duplicate the record, including calling after initialize hooks. Frozen state will not be copied, and all associations will be cleared. A duped record will return true for new_record?, have a nil id field, and is saveable.
  • The query cache now works with prepared statements. No changes in the applications are required.

7 Active Model

  • attr_accessible accepts an option :as to specify a role.
  • InclusionValidator, ExclusionValidator, and FormatValidator now accepts an option which can be a proc, a lambda, or anything that respond to call. This option will be called with the current record as an argument and returns an object which respond to include? for InclusionValidator and ExclusionValidator, and returns a regular expression object for FormatValidator.
  • Added ActiveModel::SecurePassword to encapsulate dead-simple password usage with BCrypt encryption and salting.
  • ActiveModel::AttributeMethods allows attributes to be defined on demand.
  • Added support for selectively enabling and disabling observers.
  • Alternate I18n namespace lookup is no longer supported.

8 Active Resource

  • The default format has been changed to JSON for all requests. If you want to continue to use XML you will need to set self.format = :xml in the class. For example,

class User < ActiveResource::Base

self.format = :xml


9 Active Support

  • ActiveSupport::Dependencies now raises NameError if it finds an existing constant in load_missing_constant.
  • Added a new reporting method Kernel#quietly which silences both STDOUT and STDERR.
  • Added String#inquiry as a convenience method for turning a String into a StringInquirer object.
  • Added Object#in? to test if an object is included in another object.
  • LocalCache strategy is now a real middleware class and no longer an anonymous class.
  • ActiveSupport::Dependencies::ClassCache class has been introduced for holding references to reloadable classes.
  • ActiveSupport::Dependencies::Reference has been refactored to take direct advantage of the new ClassCache.
  • Backports Range#cover? as an alias for Range#include? in Ruby 1.8.
  • Added weeks_ago and prev_week to Date/DateTime/Time.
  • Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants!.


  • ActiveSupport::SecureRandom is deprecated in favor of SecureRandom from the Ruby standard library.

10 Credits

See the fulllistofcontributorstoRails for the many people who spent many hours making Rails, the stable and robust framework it is. Kudos to all of them.

Rails 3.1 Release Notes were compiled by VijayDev.

标签: gem git guide jquery learning rails release ruby

Posted in Uncategorized

版本号(the version number in baike)

版本号(version number)是版本的标识号。每一个操作系统(或广义的讲,每一个软件)都有一个版本号。版本号能使用户了解所使用的操作系统是否为最新的版本以及它所提供的功能与设施。 每一个版本号可以分为主版本号与次版本号两部分。

版本号的命名格式  例如:DOS4.0,主版本号是4,次版本号是0。


  版本控制比较普遍的 3 种命名格式 :

一、 GNU 风格的版本号命名格式

  主版本号 . 子版本号 [. 修正版本号 [. 编译版本号 ]]


  英文对照 : Major_Version_Number.Minor_Version_Number[.Revision_Number[.Build_Number]]


  示例 : 1.2.1, 2.0, 5.0.0 build-13124

二、 Windows 风格的版本号命名格式

  主版本号 . 子版本号 [ 修正版本号 [. 编译版本号 ]]


  英文对照 : Major_Version_Number.Minor_Version_Number[Revision_Number[.Build_Number]]


  示例: 1.21, 2.0

三、.Net Framework 风格的版本号命名格式



  英文对照: Major_Version_Number.Minor_Version_Number[.Build_Number[.Revision_Number]]


  版本号由二至四个部分组成:主版本号、次版本号、内部版本号和修订号。主版本号和次版本号是必选的;内部版本号和修订号是可选的,但是如果定义了修订号部分,则内部版本号就是必选的。所有定义的部分都必须是大于或等于 0 的整数。




  Major :具有相同名称但不同主版本号的程序集不可互换。例如,这适用于对产品的大量重写,这些重写使得无法实现向后兼容性。


  Minor :如果两个程序集的名称和主版本号相同,而次版本号不同,这指示显著增强,但照顾到了向后兼容性。例如,这适用于产品的修正版或完全向后兼容的新版本。


  Build :内部版本号的不同表示对相同源所作的重新编译。这适合于更改处理器、平台或编译器的情况。


  Revision :名称、主版本号和次版本号都相同但修订号不同的程序集应是完全可互换的。这适用于修复以前发布的程序集中的安全漏洞。


  程序集的只有内部版本号或修订号不同的后续版本被认为是先前版本的修补程序 (Hotfix) 更新。



一、 GNU 风格的版本号管理策略

  1.项目初版本时 , 版本号可以为 0.1 或 0.1.0, 也可以为 1.0 或 1.0.0, 如果你为人很低调 , 我想你会选择那个主版本号为 0 的方式 ;


  2.当项目在进行了局部修改或 bug 修正时 , 主版本号和子版本号都不变 , 修正版本号加 1;


  3. 当项目在原有的基础上增加了部分功能时 , 主版本号不变 , 子版本号加 1, 修正版本号复位为 0, 因而可以被忽略掉 ;


  4.当项目在进行了重大修改或局部修正累积较多 , 而导致项目整体发生全局变化时 , 主版本号加 1;


  5.另外 , 编译版本号一般是编译器在编译过程中自动生成的 , 我们只定义其格式 , 并不进行人为控制 .

二、 Window 下的版本号管理策略

  1.目初版时 , 版本号为 1.0 或 1.00;


  2. 当项目在进行了局部修改或 bug 修正时,主版本号和子版本号都不变 , 修正版本号加 1;


  3. 当项目在原有的基础上增加了部分功能时 , 主版本号不变 , 子版本号加 1, 修正版本号复位为 0, 因而可以被忽略掉 ;


  4. 当项目在进行了重大修改或局部修正累积较多 , 而导致项目整体发生全局变化时 , 主版本号加 1;


  5. 另外 , 编译版本号一般是编译器在编译过程中自动生成的 , 我们只定义其格式 , 并不进行人为控制 .


  另外 , 还可以在版本号后面加入 Alpha, Beta, Gamma, Current, RC (Release Candidate), Release, Stable 等后缀 , 在这些后缀后面还可以加入 1 位数字的版本号 .


  对于用户来说 , 如果某个软件的主版本号进行了升级 , 用户还想继续那个软件 , 则发行软件的公司一般要对用户收取升级费用 ; 而如果子版本号或修正版本号发生了升级 , 一般来说是免费的 .



  Alpha — 内部测试版 Beta — 外部测试版


  Cardware — 属共享软件的一种,只要给作者回复一封电邮或明信片即可。(有的作者并由此提供注册码等),目前这种形式已不多见。


  CHT — 繁体中文版


  CN/SPC — 简体中文版


  Corporation & Enterprise — 企业版


  Deluxe — 豪华版


  Demo — 演示版


  Dev — 开发专用版,程序员版本。


  EN — 英文版


  Enhance — 增强版或者加强版 属于正式版


  Express&Special — 特别版


  Final — 最终版


  Free — 免费版


  Full version — 完全版 属于正式版


  Green — 绿色版,破解版


  Mini — 迷你版(也叫精简版),只有最基本的功能


  Multi-language — 多语言版


  Plus — 属增强版,不过这种大部分是在程序界面及多媒体功能上增强。


  Premium — 增强版


  Preview — 预览版


  Professional — 专业版


  Regged/Registered — 已注册版


  Release — 发行版 有时间限制


  Retail/RTM — 零售版


  Shareware — 共享版


  Stable — 稳定版


  Standard — 标准版


  Ultimate — 旗舰版,最终版本


  Upgrade — 升级版






  此版本表示该软件仅仅是一个初步完成品,通常只在软件开发者内部交流,也有很少一部分发布给专业测试人员。一般而言,该版本软件的 bug 较多,普通用户最好不要安装。
















  未注册版与试用版极其类似,只是未注册版通常没有时间限制,在功能上相对于正式版做了一定的限制,例如绝大多数网络电话软件的注册版和未注册版,两者之间在通话质量上有很大差距。还有些虽然在使用上与正式版毫无二致,但是动不动就会弹出一个恼人的消息框来提醒你注册,如看图软件 acdsee 、智能陈桥汉字输入软件等。




  也称为演示版,在非正式版软件中,该版本的知名度最大。 demo 版仅仅集成了正式版中的几个功能,颇有点像 unregistered 。不同的是, demo 版一般不能通过升级或注册的方法变为正式版。


  以上是软件正式版本推出之前的几个版本,α、β、γ可以称为测试版,大凡成熟软件总会有多个测试版,如 windows 98 的β版,前前后后将近有 10 个。这么多的测试版一方面为了最终产品尽可能地满足用户的需要,另一方面也尽量减少了软件中的 bug 。而 trial 、 unregistered 、 demo 有时统称为演示版,这一类版本的广告色彩较浓,颇有点先尝后买的味道,对于普通用户而言自然是可以免费尝鲜了。






  该版本意味“最终释放版”,在出了一系列的测试版之后,终归会有一个正式版本,对于用户而言,购买该版本的软件绝对不会错。该版本有时也称为标准版。一般情况下, release 不会以单词形式出现在软件封面上,取而代之的是符号 (r) ,如 windows nt(r) 4.0 、 ms-dos(r) 6.22 等。




  很显然,该版本是与 unregistered 相对的注册版。注册版、 release 和下面所讲的 standard 版一样,都是软件的正式版本,只是注册版软件的前身有很大一部分是从网上下载的。












  该版本型号常见于百科全书中,比较有名的是微软的 encarta 系列。 reference 是最高级别,其包含的主题、图像、影片剪辑等相对于 standard 和 deluxe 版均有大幅增加,容量由一张光盘猛增至三张光盘,并且加入了很强的交互功能,当然价格也不菲。可以这么说,这一版本的百科全书才能算是真正的百科全书,也是发烧友们收藏的首选。




  专业版是针对某些特定的开发工具软件而言的。专业版中有许多内容是标准版中所没有的,这些内容对于一个专业的软件开发人员来说是极为重要的。如微软的 visual foxpro 标准版并不具备编译成可执行文件的功能,这对于一个完整的开发项目而言显然是无法忍受的,若客户机上没有 foxpro 将不能使用。如果用专业版就没有这个问题了。




  企业版是开发类软件中的极品(相当于百科全书中的 reference 版)。拥有一套这种版本的软件可以毫无障碍地开发任何级别的应用软件。如著名的 visual c++ 的企业版相对于专业版来说增加了几个附加的特性,如 sql 调试、扩展的存储过程向导、支持 as/400 对 ole db 的访问等。而这一版本的价格也是普通用户无法接受的。如微软的 visual studios 6.0 enterprise 中文版的价格为 23000 元。






  升级版的软件是不能独立使用的,该版本的软件在安装过程中会搜索原有的正式版,如果不存在,则拒绝执行下一步。如 microsoft office 2000 升级版、 windows 9x 升级版等等。




  OEM 版通常是捆绑在硬件中而不单独销售的版本。将自己的产品交给别的公司去卖,保留自己的著作权,双方互惠互利,一举两得。












  以上是一些常见软件版本的简要介绍,随着软件市场行为的变化,现在也出现了一些新的版本命名方式,比如windows xp中的xp是取自于experience中的第二、第三个字母。希望以上内容能够对大家的购买、使用和下载软件有所帮助。


  基于商业上考虑,很多的软件都不是非常严谨的遵循这个规则的。最有名的就是微软了。例如他的 NT 系列版本。大家比较熟悉的是从 NT 4.0 开始的。 99 年推出了 windows 2000 , 2001 年推出了 windows xp , 2003 年推出了 windows 2003 ,乍一看版本区别蛮大的,但是看他们的内部版本号就会发现,变化其实并不大,只是界面变化的大了而已。这是软件公司经常干的事情。 Windows 2000 的版本号是 NT 5.0 , windows xp 的版本号是 NT 5.1 , windows 2003 的版本号是 NT 5.2 ,Windows Vista和现在的Windows7 的版本号是 NT 6.0和NT 6.1,才是跨越化的版本。这样做的话就可以持续的赚广大客户的钱。毕竟人的眼睛看得东西是最直观的,所以给人感觉也是变化最大的 。

Posted in Uncategorized

Rails Routing from the Outside In Rails

Rails Routing from the Outside In Rails来自外部的Routing

This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:


Understand the code in routes.rb


  • Construct your own routes, using either the preferred resourceful style or the match method

构建属于你的routes,要么首选使用resourceful style要么使用match方法

  • Identify what parameters to expect an action to receive


  • Automatically create paths and URLs using route helpers

自动的创建路径和URLs使用route helpers

  • Use advanced techniques such as constraints and Rack endpoints

使用高级的技术比如公约和Rack endpoints

1 The Purpose of the Rails Router

The Rails router recognizes URLs and dispatches them to a controller’s action. It can also generate paths and URLs, avoiding the need to hardcode strings in your views.

Rails router组织URLsdispatches(调度)到一个controlleraction中。它也可以创建pathsURLs,避免需要hardcode string到你的视图中。

1.1 Connecting URLs to Code连接URLsCode

When your Rails application receives an incoming request

当你的Rails应用程序收到一个传入请求(incoming requests (传入请求)正传递给用户的网站内容。)

GET /patients/17

it asks the router to match it to a controller action. If the first matching route is

它请求router匹配URLs到一个controller action。如果第一个匹配的route

match “/patients/:id” => “patients#show”

the request is dispatched to the patients controller’s show action with { :id =>17} in params.

这个请求被调度给patients controllershow action以及{ :id =>17}params字典中。

1.2 Generating Paths and URLs from CodeCode创建PathsURLs

You can also generate paths and URLs. If your application contains this code:


@patient = Patient.find(17)

<%= link_to “Patient Record”, patient_path(@patient) %>

The router will generate the path /patients/17. This reduces the brittleness of your view and makes your code easier to understand. Note that the id does not need to be specified in the route helper.

Router将会创建path /patients/17。这样减少了你的视图的脆性并且使得你的代码更加容易明白。

2 Resource Routing: the Rails Default

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update and destroy actions, a resourceful route declares them in a single line of code.

Resource routing让你快速的为一个提供的resourcefulcontroller声明所有的常用routes。替代你去声明单个的index, show, new, edit, create, update and destroy actionsroutes,一个resourceful route声明它们在一个单行代码中。

When your Rails application receives an incoming request for


DELETE /photos/17

it asks the router to map it to a controller action. If the first matching route is

它请求router匹配URLs到一个controller action。如果第一个匹配的route

resources :photos

Rails would dispatch that request to the destroy method on the photos controller with { :id =>17} in params.

Rails将会把这个请求调度给photos controllerdestroy action以及{ :id =>17}params字典中

2.2 CRUD, Verbs, and Actions



In Rails, a resourceful route provides a mapping between HTTP verbs and URLs to controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as

Rails中,一个resourceful route提供一个在HTTP verbsURLs之间的映射到controller actions。根据公约,每个action都应该映射到数据库的CRUD操作的一部分。一个单独的条目在routing文件中,像这样

resources :photos

creates seven different routes in your application, all mapping to the Photos controller:

创建七个不同的routes在你的应用程序中,所有的这些routes映射到Photos controller


HTTP Verb Path action used for
GET /photos index display a list of all photos
GET /photos/new new return an HTML form for creating a new photo
POST /photos create create a new photo
GET /photos/:id show display a specific photo
GET /photos/:id/edit edit return an HTML form for editing a photo
PUT /photos/:id update update a specific photo
DELETE /photos/:id destroy delete a specific photo

Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action’s route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.

Rails routes在它们指定的顺序中匹配,因此如果你有一个resources :photosget 'photos/poll'的上面,resources lineshow actionroute将会在get line之前先被匹配。要修复这些,移动get lineresources line上面以确保get line被首先匹配。

2.3 Paths and URLs

Creating a resourceful route will also expose a number of helpers to the controllers in your application. In the case of resources :photos:

在你的应用程序中创建一个resourcefulroute也将会摆出一系列的controllershelpers,在这里的情况中resources :photos如下:

  • photos_path returns /photos
  • new_photo_path returns /photos/new
  • edit_photo_path(:id) returns /photos/:id/edit (for instance, edit_photo_path(10) returns /photos/10/edit)
  • photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10)

Each of these helpers has a corresponding _url helper (such as photos_url) which returns the same path prefixed with the current host, port and path prefix.

这里的每个helpers都有一个相应的_url helper(例如photos_urledit_photo_url(1)


####the code in my demo#####





Because the router uses the HTTP verb and URL to match inbound requests, four URLs map to seven different actions.

因为router使用HTTP verbURL来匹配入站请求,四种URLs映射到七种不同的actions中。

2.4 Defining Multiple Resources at the Same Time在同一时间定义多个Resource

If you need to create routes for more than one resource, you can save a bit of typing by defining them all with a single call to resources:


resources :photos, :books, :videos

This works exactly the same as


resources :photos

resources :books

resources :videos

2.5 Singular Resources 单数Resources

Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action.

有时候,你有一个resourceclients通常查找它们并不引用一个ID。例如,你将会希望/profile来总是显示当前的登录的用户的profile。在这种情况中,你可以使用一个单数的resource来映射/profile (rather than /profile/:id)show ation

match “profile” => “users#show”

This resourceful route这里是resourceful route

resource :geocoder

creates six different routes in your application, all mapping to the Geocoders controller:



HTTP Verb Path action used for
GET /geocoder/new new return an HTML form for creating the geocoder
POST /geocoder create create the new geocoder
GET /geocoder show display the one and only geocoder resource
GET /geocoder/edit edit return an HTML form for editing the geocoder
PUT /geocoder update update the one and only geocoder resource
DELETE /geocoder destroy delete the geocoder resource

Because you might want to use the same controller for a singular route (/account) and a plural route (/accounts/45), singular resources map to plural controllers.


A singular resourceful route generates these helpers:

一个单数resourceful route创建这些helpers

  • new_geocoder_path returns /geocoder/new
  • edit_geocoder_path returns /geocoder/edit
  • geocoder_path returns /geocoder

As with plural resources, the same helpers ending in _url will also include the host, port and path prefix.

就像plural resources,相同的以_url结尾的helpers同样包含,hostport和路径后缀。

2.6 Controller Namespaces and Routing

You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an Admin:: namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:

你可能希望通过namespace分组组织controllers。通常大多数情况,你可以分组一系列的administrative controllers到一个Admin::名称空间下面。你将会放置这些controllersapp/controllers/admin目录中,并且你可以在你的router中分组他们在一起

namespace :admin do

resources :posts, :comments


This will create a number of routes for each of the posts and comments controller. For Admin::PostsController, Rails will create:

这将会对于每一个postscomments controller创建若干的routes。对于Admin::PostsControllerRails将会创建:


HTTP Verb Path action named helper
GET /admin/posts index admin_posts_path
GET /admin/posts/new new new_admin_post_path
POST /admin/posts create admin_posts_path
GET /admin/posts/:id show admin_post_path(:id)
GET /admin/posts/:id/edit edit edit_admin_post_path(:id)
PUT /admin/posts/:id update admin_post_path(:id)
DELETE /admin/posts/:id destroy admin_post_path(:id)

If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use

如果你想Admin::PostsControllerroute /posts(without the prefix /admin),你可以使用


scope :module => "admin" do

resources :posts, :comments


or, for a single case

resources :posts, :module => "admin"

If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use

scope “/admin” do

resources :posts, :comments


or, for a single case

resources :posts, :path => "/admin/posts"

In each of these cases, the named routes remain the same as if you did not use scope. In the last case, the following paths map to PostsController:

在每个这样的情况中,named routes保持不变,如果你没有使用范围。在最后,随后的paths映射到PostsController


HTTP Verb Path action named helper
GET /admin/posts index posts_path
GET /admin/posts/new new new_post_path
POST /admin/posts create posts_path
GET /admin/posts/:id show post_path(:id)
GET /admin/posts/:id/edit edit edit_post_path(:id)
PUT /admin/posts/:id update post_path(:id)
DELETE /admin/posts/:id destroy post_path(:id)

2.7 Nested Resources嵌套Resource

It’s common to have resources that are logically children of other resources. For example, suppose your application includes these models:


class Magazine < ActiveRecord::Base

has_many :ads



class Ad < ActiveRecord::Base

belongs_to :magazine


Nested routes allow you to capture this relationship in your routing. In this case, you could include this route declaration:


resources :magazines do

resources :ads


In addition to the routes for magazines, this declaration will also route ads to an AdsController. The ad URLs require a magazine:

除了magazinesroutes,这里也同样声明route adsAdsControlleradURLs需要一个magazine(对象):


HTTP Verb Path action used for
GET /magazines/:id/ads index display a list of all ads for a specific magazine
GET /magazines/:id/ads/new new return an HTML form for creating a new ad belonging to a specific magazine
POST /magazines/:id/ads create create a new ad belonging to a specific magazine
GET /magazines/:id/ads/:id show display a specific ad belonging to a specific magazine
GET /magazines/:id/ads/:id/edit edit return an HTML form for editing an ad belonging to a specific magazine
PUT /magazines/:id/ads/:id update update a specific ad belonging to a specific magazine
DELETE /magazines/:id/ads/:id destroy delete a specific ad belonging to a specific magazine

This will also create routing helpers such as magazine_ads_url and edit_magazine_ad_path. These helpers take an instance of Magazine as the first parameter (magazine_ads_url(@magazine)).

这里也将会创建routing helpers例如magazine_ads_urledit_magazine_ad_path。这些helpers获取一个Magazine的实例作为第一个参数(magazine_ads_url(@magazine))。

2.7.1 Limits to Nesting嵌套的局限

You can nest resources within other nested resources if you like. For example:


resources :publishers do

resources :magazines do

resources :photos



Deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize paths such as



The corresponding route helper would be publisher_magazine_photo_url, requiring you to specify objects at all three levels. Indeed, this situation is confusing enough that a popular article by Jamis Buck proposes a rule of thumb for good Rails design:

相应的route helper将会是publisher_magazine_photo_url这需要你指定三个级别的所有对象。事实上,这种情况下太混乱了一篇受欢迎的文章来自Jamis Buck,关于一个设计良好的Rails的经验法则:

Resources should never be nested more than 1 level deep.

2.8 Creating Paths and URLs From Objects

In addition to using the routing helpers, Rails can also create paths and URLs from an array of parameters. For example, suppose you have this set of routes:

除了使用routing helpersRails也可以从一个parameters数组创建pathsURLs。例如,假设你有这样的组routes

resources :magazines do

resources :ads


When using magazine_ad_path, you can pass in instances of Magazine and Ad instead of the numeric IDs.

在使用magazine_ad_path的时候,你可以传递Magazine and Ad的实例替代数字IDs

<%= link_to “Ad details”, magazine_ad_path(@magazine, @ad) %>

You can also use url_for with a set of objects, and Rails will automatically determine which route you want:


<%= link_to “Ad details”, url_for([@magazine, @ad]) %>

In this case, Rails will see that @magazine is a Magazine and @ad is an Ad and will therefore use the magazine_ad_path helper. In helpers like link_to, you can specify just the object in place of the full url_for call:

在这里,Rails将会明白@magazineMagazine并且@adAd于此将会因此使用magazine_ad_path helper。在就像link_tohelpers中,你可以指定仅仅对象在url_for调用中:

<%= link_to “Ad details”, [@magazine, @ad] %>

If you wanted to link to just a magazine, you could leave out the Array:


<%= link_to “Magazine details”, @magazine %>

This allows you to treat instances of your models as URLs, and is a key advantage to using the resourceful style.

这让你处理models的实例为URLs,并且这也是使用resourceful style的关键优势。

2.9 Adding More RESTful Actions添加更多的RESTful Action

You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional routes that apply to the collection or individual members of the collection.

你并不限制于RESTful routing默认创建的七个routes。如果你喜欢,你可以添加额外的routes用于多个或者个别的collection

2.9.1 Adding Member Routes

To add a member route, just add a member block into the resource block:

添加一个member route,仅仅添加一个memberblockresource block中:

resources :photos do

member do

get ‘preview’



This will recognize /photos/1/preview with GET, and route to the preview action of PhotosController. It will also create the preview_photo_url and preview_photo_path helpers.

Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use get, put, post, or delete here. If you don’t have multiple member routes, you can also pass :on to a route, eliminating the block:

memberroutes中,每个route名字指定HTTP verb这是将会组织的。在这里你可以使用get, put, post, or delete。如果你没有多个member routes,你同样也可以传递:on到一个route,消除block

resources :photos do

get ‘preview’, :on => :member


2.9.2 Adding Collection Routes

To add a route to the collection:


resources :photos do

collection do

get ‘search’



This will enable Rails to recognize paths such as /photos/search with GET, and route to the search action of PhotosController. It will also create the search_photos_url and search_photos_path route helpers.

这将使Rails能够像这样/photos/search with GET组织路径,并且routePhotosControllersearch action。它将同样创建search_photos_urlsearch_photos_path route helpers

Just as with member routes, you can pass :on to a route:

仅仅对于member routes,你可以传递:on给一个route

resources :photos do

get ‘search’, :on => :collection


2.9.3 A Note of Caution一个慎重的提醒

If you find yourself adding many extra actions to a resourceful route, it’s time to stop and ask yourself whether you’re disguising the presence of another resource.



3 Non-Resourceful Routes- Resourceful Routes

In addition to resource routing, Rails has powerful support for routing arbitrary URLs to actions. Here, you don’t get groups of routes automatically generated by resourceful routing. Instead, you set up each route within your application separately.

除了resource routingRails对任意的URLsactions有强力的支持。这里,你没有得到被resourceful routing自动创建的groups of routes。作为替代,在你的应用程序中分别设置每个route

While you should usually use resourceful routing, there are still many places where the simpler routing is more appropriate. There’s no need to try to shoehorn every last piece of your application into a resourceful framework if that’s not a good fit.

即使你应该通常使用resourceful routing,这里仍然有很多地方简单的routing更加适合。这里不需要尝试将你的应用程序最后写成一个resourceful framework如果这样并不合适。

In particular, simple routing makes it very easy to map legacy URLs to new Rails actions.

特别是,简单的路routing,使得它很容易映射(传入的)现有的URL映射到新的Rails action

3.1 Bound Parameters绑定参数

When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: :controller maps to the name of a controller in your application, and :action maps to the name of an action within that controller. For example, consider one of the default Rails routes:

当你设定一个正则route,你供应一系列的字符,其将通过Rails映射到传入HTTP请求的一部分。这些字符的两部分分别是::controller映射到你应用程序中的一个controller,并且:action映射到在指定的controller中的一个action。例如思考一个默认的Rails routes

match ‘:controller(/:action(/:id))’

If an incoming request of /photos/show/1 is processed by this route (because it hasn’t matched any previous route in the file), then the result will be to invoke the show action of the PhotosController, and to make the final parameter "1" available as params[:id]. This route will also route the incoming request of /photos to PhotosController#index, since :action and :id are optional parameters, denoted by parentheses.

如果传入请求/photos/show/1 is processed by this route (因为它并没有被先前的route文件中任何的route匹配成功),接着这个结果将会调用PhotosControllershow action,并且使得最后的参数1可用于params[:id]。这个route也还会route传入请求/photosPhotosController#index,因为:action:id是被括号包起来的可选参数。

3.2 Dynamic Segments动态分割

You can set up as many dynamic segments within a regular route as you like. Anything other than :controller or :action will be available to the action as part of params. If you set up this route:

你可以设置你希望的数目的dynamic segments在一个正则route中。超过:controller or :action的其他部分(是可用的)在action作为params第一部分。如果你设定这样的route

match ':controller/:action/:id/:user_id'

An incoming path of /photos/show/1/2 will be dispatched to the show action of the PhotosController. params[:id] will be "1", and params[:user_id] will be "2".

一个传入路径/photos/show/1/2将会被调度给PhotosControllershow actionparams[:id] will be "1", and params[:user_id] will be "2".

You can’t use namespace or :module with a :controller path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g:


match ':controller(/:action(/:id))', :controller => /admin/[^/]+/


By default dynamic segments don’t accept dots – this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment add a constraint which overrides this – for example :id => /[^/]+/ allows anything except a slash.

默认的动态分割不接受dots.——这是因为dot被作为格式化routes的一个分割。如果你需要在一个dynamic segment中使用dot,添加一个限制来重写它——例如:id => /[^/]+/允许除了斜线之外的任何字符。

3.3 Static Segments

You can specify static segments when creating a route:

match ‘:controller/:action/:id/with_user/:user_id’

This route would respond to paths such as /photos/show/1/with_user/2. In this case, params would be { :controller =>photos, :action =>show, :id =>1, :user_id =>2}.

3.4 The Query String查询字符串

The params will also include any parameters from the query string. For example, with this route:


match ‘:controller/:action/:id’

An incoming path of /photos/show/1?user_id=2 will be dispatched to the show action of the Photos controller. params will be { :controller =>photos, :action =>show, :id =>1, :user_id =>2}.

一个传入路径/photos/show/1?user_id=2将会被调度给Photos controllershow actionparams将会是{ :controller =>photos, :action =>show, :id =>1, :user_id =>2}

3.5 Defining Defaults默认定义

You do not need to explicitly use the :controller and :action symbols within a route. You can supply them as defaults:


match ‘photos/:id’ => ‘photos#show’

With this route, Rails will match an incoming path of /photos/12 to the show action of PhotosController.

通过这个routeRails将会匹配一个传入路径/photos/12PhotosControllershow action

You can also define other defaults in a route by supplying a hash for the :defaults option. This even applies to parameters that you do not specify as dynamic segments. For example:


match ‘photos/:id’ => ‘photos#show’, :defaults => { :format => ‘jpg’ }

Rails would match photos/12 to the show action of PhotosController, and set params[:format] to "jpg".

Rails将会匹配photos/12PhotosControllershow action,并且设置params[:format] to "jpg"

3.6 Naming Routes

You can specify a name for any route using the :as option.


match ‘exit’ => ‘sessions#destroy’, :as => :logout

This will create logout_path and logout_url as named helpers in your application. Calling logout_path will return /exit


3.7 HTTP Verb Constraints 限定HTTP 动作

You can use the :via option to constrain the request to one or more HTTP methods:


match ‘photos/show’ => ‘photos#show’, :via => :get

There is a shorthand version of this as well:


get ‘photos/show’

You can also permit more than one verb to a single route:


match ‘photos/show’ => ‘photos#show’, :via => [:get, :post]

3.8 Segment Constraints分割限制

You can use the :constraints option to enforce a format for a dynamic segment:


match ‘photos/:id’ => ‘photos#show’, :constraints => { :id => /[A-Z]d{5}/ }

This route would match paths such as /photos/A12345. You can more succinctly express the same route this way:


match ‘photos/:id’ => ‘photos#show’, :id => /[A-Z]d{5}/

:constraints takes regular expressions with the restriction that regexp anchors can’t be used. For example, the following route will not work:


match ‘/:id’ => ‘posts#show’, :constraints => {:id => /^d/}

However, note that you don’t need to use anchors because all routes are anchored at the start.


For example, the following routes would allow for posts with to_param values like 1-hello-world that always begin with a number and users with to_param values like david that never begin with a number to share the root namespace:


match ‘/:id’ => ‘posts#show’, :constraints => { :id => /d.+/ }

match ‘/:username’ => ‘users#show’

3.9 Request-Based Constraints Request-Based的限制

You can also constrain a route based on any method on the Request object that returns a String.

You specify a request-based constraint the same way that you specify a segment constraint:

你也可以限制一个route 基于任何方法在Request对象时它都会返回一个String

你指定一个request-basedcontraint和你指定一个segment constaint是一样的。

match “photos”, :constraints => {:subdomain => “admin”}

You can also specify constraints in a block form:

你也可以指定限制在一个block form中:

namespace :admin do

constraints :subdomain => “admin” do

resources :photos



3.10 Advanced Constraints高级constraints

If you have a more advanced constraint, you can provide an object that responds to matches? that Rails should use. Let’s say you wanted to route all users on a blacklist to the BlacklistController. You could do:



class BlacklistConstraint

def initialize

@ips = Blacklist.retrieve_ips



def matches?(request)





TwitterClone::Application.routes.draw do

match “*path” => “blacklist#index”,

:constraints =>


3.11 Route Globbing

Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example

Route globbing是一种方式来指定特定的paramerter应该被一个route的其余的所有部分匹配。例如

match ‘photos/*other’ => ‘photos#unknown’

This route would match photos/12 or /photos/long/path/to/12, setting params[:other] to "12" or "long/path/to/12".

这个route将会匹配photos/12或者/photos/long/path/to/12,设置params[:other] to "12""long/path/to/12"

Wildcard segments can occur anywhere in a route. For example,


match ‘books/*section/:title’ => ‘books#show’

would match books/some/section/last-words-a-memoir with params[:section] equals "some/section", and params[:title] equals "last-words-a-memoir".


Technically a route can have even more than one wildcard segment. The matcher assigns segments to parameters in an intuitive way. For example,


match ‘*a/foo/*b’ => ‘test#index’ # *a这一部分通配为a

would match zoo/woo/foo/bar/baz with params[:a] equals "zoo/woo", and params[:b] equals "bar/baz".

Starting from Rails 3.1, wildcard routes will always match the optional format segment by default. For example if you have this route:

match '*pages' => 'pages#show'

By requesting "/foo/bar.json", your params[:pages] will be equals to "foo/bar" with the request format of JSON. If you want the old 3.0.x behavior back, you could supply :format => false like this:

match '*pages' => 'pages#show', :format => false

If you want to make the format segment mandatory, so it cannot be omitted, you can supply :format => true like this:

match '*pages' => 'pages#show', :format => true

3.12 Redirection

You can redirect any path to another path using the redirect helper in your router:

你可以重定向任何path到另一个path使用redirect helper在你的router

match “/stories” => redirect(“/posts”)

You can also reuse dynamic segments from the match in the path to redirect to:

match “/stories/:name” => redirect(“/posts/%{name}”)

You can also provide a block to redirect, which receives the params and (optionally) the request object:

match “/stories/:name” => redirect {|params| “/posts/#{params[:name].pluralize}” }

match “/stories” => redirect {|p, req| “/posts/#{req.subdomain}” }

In all of these cases, if you don’t provide the leading host (, Rails will take those details from the current request.

3.13 Routing to Rack Applications

Instead of a String, like "posts#index", which corresponds to the index action in the PostsController, you can specify any Rackapplication as the endpoint for a matcher.

match “/application.js” => Sprockets

As long as Sprockets responds to call and returns a [status, headers, body], the router won’t know the difference between the Rack application and an action.

For the curious, "posts#index" actually expands out to PostsController.action(:index), which returns a valid Rack application.

3.14 Using root

You can specify what Rails should route "/" to with the root method:

root :to => ‘pages#main’

You should put the root route at the top of the file, because it is the most popular route and should be matched first. You also need to delete the public/index.html file for the root route to take effect.

4 Customizing Resourceful Routes

While the default routes and helpers generated by resources :posts will usually serve you well, you may want to customize them in some way. Rails allows you to customize virtually any generic part of the resourceful helpers.

4.1 Specifying a Controller to Use

The :controller option lets you explicitly specify a controller to use for the resource. For example:

resources :photos, :controller => “images”

will recognize incoming paths beginning with /photos but route to the Images controller:

HTTP Verb Path action named helper
GET /photos index photos_path
GET /photos/new new new_photo_path
POST /photos create photos_path
GET /photos/:id show photo_path(:id)
GET /photos/:id/edit edit edit_photo_path(:id)
PUT /photos/:id update photo_path(:id)
DELETE /photos/:id destroy photo_path(:id)

Use photos_path, new_photo_path, etc. to generate paths for this resource.

4.2 Specifying Constraints

You can use the :constraints option to specify a required format on the implicit id. For example:

This declaration constraints the :id parameter to match the supplied regular expression. So, in this case, the router would no longer match /photos/1 to this route. Instead, /photos/RR27 would match.

You can specify a single constraint to apply to a number of routes by using the block form:

constraints(:id => /[A-Z][A-Z][0-9]+/) do

resources :photos

resources :accounts


Of course, you can use the more advanced constraints available in non-resourceful routes in this context.


By default the :id parameter doesn’t accept dots – this is because the dot is used as a separator for formatted routes. If you need to use a dot within an :id add a constraint which overrides this – for example :id => /[^/]+/ allows anything except a slash.

4.3 Overriding the Named Helpers

The :as option lets you override the normal naming for the named route helpers. For example:

resources :photos, :as => “images”

will recognize incoming paths beginning with /photos and route the requests to PhotosController, but use the value of the :as option to name the helpers.

HTTP verb Path action named helper
GET /photos index images_path
GET /photos/new new new_image_path
POST /photos create images_path
GET /photos/:id show image_path(:id)
GET /photos/:id/edit edit edit_image_path(:id)
PUT /photos/:id update image_path(:id)
DELETE /photos/:id destroy image_path(:id)

4.4 Overriding the new and edit Segments重写newedit Segments

The :path_names option lets you override the automatically-generated “new” and “edit” segments in paths:

resources :photos, :path_names => { :new => ‘make’, :edit => ‘change’ }

This would cause the routing to recognize paths such as



The actual action names aren’t changed by this option. The two paths shown would still route to the new and edit actions.


If you find yourself wanting to change this option uniformly for all of your routes, you can use a scope.

scope :path_names => { :new => “make” } do

# rest of your routes


4.5 Prefixing the Named Route Helpers

You can use the :as option to prefix the named route helpers that Rails generates for a route. Use this option to prevent name collisions between routes using a path scope

scope “admin” do

resources :photos, :as => “admin_photos”



resources :photos

This will provide route helpers such as admin_photos_path, new_admin_photo_path etc.这将会提供比如 admin_photos_path, new_admin_photo_path等这样的route helpers

To prefix a group of route helpers, use :as with scope:

scope “admin”, :as => “admin” do

resources :photos, :accounts



resources :photos, :accounts

This will generate routes such as admin_photos_path and admin_accounts_path which map to /admin/photos and /admin/accounts respectively.

The namespace scope will automatically add :as as well as :module and :path prefixes.

You can prefix routes with a named parameter also:

scope “:username” do

resources :posts


This will provide you with URLs such as /bob/posts/1 and will allow you to reference the username part of the path as params[:username] in controllers, helpers and views.

4.6 Restricting the Routes Created限制routes被创建

By default, Rails creates routes for the seven default actions (index, show, new, create, edit, update, and destroy) for every RESTful route in your application. You can use the :only and :except options to fine-tune this behavior. The :only option tells Rails to create only the specified routes:

默认的,Rails按照七种默认的actionindex, show, new, create, edit, update, and destroy)为你应用程序中的每个RESTful route创建routes

resources :photos, :only => [:index, :show]

Now, a GET request to /photos would succeed, but a POST request to /photos (which would ordinarily be routed to the create action) will fail.

现在一个GET请求到/photos将会成功,但是一个POST/photos(其按理将会routecreate action)将会失败。

The :except option specifies a route or list of routes that Rails should not create:

resources :photos, :except => :destroy

In this case, Rails will create all of the normal routes except the route for destroy (a DELETE request to /photos/:id).

If your application has many RESTful routes, using :only and :except to generate only the routes that you actually need can cut down on memory use and speed up the routing process.

如果你的应用程序中有很多 RESTful routes,使用:only and :except来生成仅仅你实际需要的route能够消减内存使用和提速routing 进程。

4.7 Translated Paths翻译路径

Using scope, we can alter path names generated by resources:


scope(:path_names => { :new => “neu”, :edit => “bearbeiten” }) do

resources :categories, :path => “kategorien”


Rails now creates routes to the CategoriesController.

HTTP verb Path action named helper
GET /kategorien index categories_path
GET /kategorien/neu new new_category_path
POST /kategorien create categories_path
GET /kategorien/:id show category_path(:id)
GET /kategorien/:id/bearbeiten edit edit_category_path(:id)
PUT /kategorien/:id update category_path(:id)
DELETE /kategorien/:id destroy category_path(:id)

4.8 Overriding the Singular Form

If you want to define the singular form of a resource, you should add additional rules to the Inflector.


ActiveSupport::Inflector.inflections do |inflect|

inflect.irregular ‘tooth’, ‘teeth’


4.9 Using :as in Nested Resources在嵌套resources中使用:as

The :as option overrides the automatically-generated name for the resource in nested route helpers. For example,


resources :magazines do

resources :ads, :as => ‘periodical_ads’


This will create routing helpers such as magazine_periodical_ads_url and edit_magazine_periodical_ad_path.

5 Inspecting and Testing Routes检查和测试routes

Rails offers facilities for inspecting and testing your routes.


5.1 Seeing Existing Routes with rake使用rake来查看存在的routes

If you want a complete list of all of the available routes in your application, run rake routes command. This will print all of your routes, in the same order that they appear in routes.rb. For each route, you’ll see:

如果你需要一个你应用程序中可用的完整的list,运行 rake routes命令。这将会打印所有你的routes(到终端),与routes.rb中出现的顺序一样。对于每个route,你将会看到:

  • The route name (if any)
  • The HTTP verb used (if the route doesn’t respond to all verbs)
  • The URL pattern to match 匹配的URL模式
  • The routing parameters for the route

For example, here’s a small section of the rake routes output for a RESTful route:

          users GET  /users          {:controller=>"users", :action=>"index"}
formatted_users GET  /users.:format  {:controller=>"users", :action=>"index"}
                POST /users          {:controller=>"users", :action=>"create"}
                POST /users.:format  {:controller=>"users", :action=>"create"}

You may restrict the listing to the routes that map to a particular controller setting the CONTROLLER environment variable:

你可以限制列出的routes映射到一个别的controller设置 CONTROLLER环境变量:

$ CONTROLLER=users rake routes

You’ll find that the output from rake routes is much more readable if you widen your terminal window until the output lines don’t wrap.

你会发现如果你扩大到你的终端不自动换行,来自rake routes会更具可读性。

5.2 Testing Routes

Routes should be included in your testing strategy策略 (just like the rest of your application). Rails offers three built-in assertions designed to make testing routes simpler:

  • assert_generates
  • assert_recognizes
  • assert_routing
5.2.1 The assert_generates Assertion

assert_generates asserts that a particular set of options generate a particular path and can be used with default routes or custom routes.


assert_generates “/photos/1″, { :controller => “photos”, :action => “show”, :id => “1” }

assert_generates “/about”, :controller => “pages”, :action => “about”

5.2.2 The assert_recognizes Assertion

assert_recognizes is the inverse of assert_generates. It asserts that a given path is recognized and routes it to a particular spot in your application.


assert_recognizes({ :controller => "photos", :action => "show", :id => "1" }, "/photos/1")

You can supply a :method argument to specify the HTTP verb:

你可以提供一个:method参数来指定HTTP verbe

assert_recognizes({ :controller => “photos”, :action => “create” }, { :path => “photos”, :method => :post })

assert_recognizes({ :controller => “photos”, :action => “create” }, { :path => “photos”, :method => :post })

5.2.3 The assert_routing Assertion

The assertion checks the route both ways: it tests that the path generates the options, and that the options generate the path. Thus, it combines the functions of assert_generates and assert_recognizes.

断言 assert_routing检测route两方面:它测试访问路径生成选项,并且测试这个选项生成的路径。这样,它联合了 assert_generates and assert_recognizes的功能。

assert_routing({ :path => “photos”, :method => :post }, { :controller => “photos”, :action => “create” })

标签: guide http rails route ruby translate

Posted in Uncategorized



  1. 两个月前你从没听说过JSON
  2. 一个月前你听说了这个词但没有留意
  3. 一周前你发现这个词被提到多次,开始想,没错 … 又有一些垃圾东西要学了
  4. 今天你被心灵深处的一个闹铃闹醒,心想:这该死的json究竟是个什么东西?为什么突然间到处都是它了!


这就开始了 …


JavaScript Object Notation.

[一个滑稽的名字。它应该被称作Lightweight Ecmascript Object Notation, 或简称 'LEON'。 ;-) ]




点击收起{"skillz": {
		{"name": "html",
		 "years": "5"
		{"name": "css",
		 "years": "3"
		{"name": "sql",
		 "years": "7"



  1. 花括弧表示一个“容器”
  2. 方括号装载数组
  3. 名称和值用冒号隔开
  4. 数组元素通过逗号隔开





  1. 他们都“自我描述”,这意味着值都是可列举的,是“人类可读”的
  2. 都是有层级的。(例如你可以在值里再存放值)
  3. 都能被多种的编程语言解析和使用
  4. 都能使用AJAX方法来传递(例如httpWebRequest)


  1. XML里在元素的开始和结尾处有尖括号和标签名:JSON使用花括号,而且只在数据的开始和结束时使用。
  2. JSON更简练,毫无疑问更适合人类书写,也许也能让我们更快速的阅读。
  3. JSON可以在JavaScript里简单的传递到eval()方法里使用
  4. JSON里有数组{每个元素没有自己的名称}
  5. 在XML里你可以对一个元素使用任意想要的名称,在JSON里你不能使用Javascript里的保留字





  1. 取回一个XML文件
  2. 循环它,从中提取值
  3. 处理这些值,等



  1. 取回JSON字符串。
  2. ‘eval’ JSON数据





Thomas Frank写了一个灵巧的javascript库,叫做classyJSON,它在JSON代码上增加了继承和定义范围等特征。




就我所知,JSON是由一个叫做Douglas Crockford的家伙发明的。如果你喜欢的话,可以看一下他的网站,他非常的有趣。



(边注:如果你把 { 和 } 替换成”<” 和 “/>”,把”:” 换成 “/”… 你会得到一个非常像gaXml的东西。有趣的世界。

(边注2:Jason 和 Ajax 都是希腊神话中的英雄。预告:另外一些即将出现的技术垃圾包括:Heracles, Perseus, Deucalion, Theseus
and Bellerophon。)

Posted in Uncategorized

16 条技巧让你更高效使用 SSH


1. 多条连接共享


ControlMaster auto
ControlPath /tmp/ssh_mux_%h_%p_%r





连接共享不止可以帮助你共享多个SSH连接,如果你需要通过SFTP与服务器传输文件,你会发现,它们使用的依然是同一条连接,如果你使用的 Bash,你会发现,你甚至SSH甚至支持Tab对服务器端文件进行自动补全,共享连接选项对于那些需要借助SSH的工具,比如rsync,git等等也 同样有效。

2. 长连接


ControlPersist 4h

现在你每次通过SSH与服务器建立连接之后,这条连接将被保持4个小时,即使在你退出服务器之后,这条连接依然可以重用,因此,在你下一次(4小时 之内)登录服务器时,你会发现连接以闪电般的速度建立完成,这个选项对于通过scp拷贝多个文件提速尤其明显,因为你不在需要为每个文件做单独的认证了。

3. 别再输入密码

如果你还在通过密码方式登录SSH,那么你或许应该试试SSH Keys,首先使用OpenSSH为自己声称一对密钥:

$ ssh-keygen


$ ssh-copy-id


$ < ~/.ssh/ ssh ‘mkdir -p .ssh; cat >> .ssh/authorized_keys; chmod go-w .ssh .ssh/authorized_keys’


为Putty配置SSH Key

Putty也可以使用SSH Key,从Putty网站下载PuttyGen和Pageant,然后使用PuttyGen生成你的密钥,将公钥拷贝到服务器的’.ssh/authorized_keys’目录,然后运行Pageant,导入你的私钥,让它在后台运行,险隘你就可以使用Putty通过公钥直接登录服务器了,你可以在Putty手册的第8,9章了解关于这一特性的详细介绍。

4. 连接中转


www1 $ scp -pr templates www2:$PWD

(顺便说一下,当你需要在两台服务器间拷贝文件时,$PWD变量时非常有用的),因为即使你已经在两台服务器上添加了你本地电脑的公钥,scp默认 仍然会提示你输入密码:这是因为你用来作为跳板的那台服务器上并没有你的私钥,所以,第二胎服务器会拒绝你的公钥,但是一定不要通过将你的私钥拷贝到中转 服务器上来解决这个问题,你可以使用agent forwarding来解决这个问题,只要在你的.ssh/config文件中加入下面这行代码就可以了:

ForwardAgent yes

或者是在Putty中勾上“Allow agent forwarding”选项,现在你的本地SSH就变成了第一台服务器的SSH代理,从第一台服务器在连接其它服务器就变和和在你本地一样简单,注意,如果要开启这个选项,前提是这个中间服务器值得你信任。

5. 省略主机名





prepend domain-search “”, “”;

然后你需要重启网络:$ sudo restart network-manager


5. 主机别名


Host dev


Host dev intranet backup

Host www* mail


7. 省去用户名


Host www* mail
User simon

现在就算我的本地用户名是 smylers,我仍然可以这样连接我的服务器:

$ ssh www2


8. 在服务器间跳转

有些时候,你可能没法直接连接到某台服务器,而需要使用一台中间服务器进行中转,这个过程也可以自动化。首先确保你已经为服务器配置了公钥访问,并开启了agent forwarding,现在你就可以通过2条命令来连接目标服务器,不会有任何提示输入:

$ ssh gateway
gateway $ ssh db


Host db
ProxyCommand ssh gateway netcat -q 600 %h %p


$ ssh db


9. 突破网络封锁


Port 443


$ sudo reload ssh

当然这样做的前提是你的服务器没有使用HTTS服务,但是实际上你只需要设置一台服务器使用https端口就够了,你但你可以访问这台服务器,你就 可以使用我们前面提到的技术利用它作为跳板来访问其它服务器,但是记住,你需要提前配置好这台服务器(现在怎么样?),这样万一当你身处一个只能访问 Web的网络环境时,就可以省掉打电话让其他人帮你配置中间服务器的麻烦了。

10. 穿越Web代理


ProxyCommand corkscrew 8080 %h %p

11. 远程GUI

有时候通过本地的GUI程序来访问远程服务器的文件会非常有用,比如,编辑一副图片,或者查看一个PDF文件,或者只是简单的通过一个非命令行的编 辑器来修改代码,我发现GVim要比终端里的Vim更有用,因为我可以通过gvimopens打开一个新窗口来编辑文件,而用当前的SSH窗口继续执行其 它操作,不要要这样做,你需要先在你的SSH配置中开启一个叫做X forwarding的选项:

ForwardX11 yes

这个选项需要服务器配置才能起作用,服务器也需要开启X forwarding,你可以在服务器的/etc/ssh/sshd_config中添加下面这个命令:

X11Forwarding yes

同时你还需要确保安装了xauth,编辑器,图片查看器以及其它的你需要运行的图形化程序,这种方式只有在支持本地X服务器的操作提供才可以工 作,mac和Windows上都有免费的X Server,你可能需要花些时间配置它们,相比之下,切换到Linux相对会更容易一下。



$ mkdir gallery_src
$ sshfs dev:projects/gallery/src gallery_src
$ cd gallery_src
$ ls


$ cd ..
$ fusermount -u gallery_src


13. 通过Vim访问远程文件

Vim有一个内置的功能可以直接编辑远程文件,需要借助SCP URL:

$ gvim scp://dev/projects/gallery/src/templates/


:help netrw-problems

14. 使用本地App连接远程服务器

有时可能有些服务,比如数据库或是Web服务器,它们运行在远程服务器上,但是如果有用方式可以直接从本地程序连接它们,那会非常有用,要做到这一 点,你需要用到端口转发(port forwarding),举个例子,如果你的服务器运行Postgres(并且只允许本地访问),那么你就可以在你的SSH配置中加入:

Host db
LocalForward 5433 localhost:5432

现在当你连接你的SSH服务器时,它会在你本地电脑打开一个5433端口(我随便挑的),并将所有发送到这个端口的数据转发到服务器的5432端口 (Postgres的默认端口),然后,只要你和服务器建立了连接,你就可以通过5433端口来访问服务器的Postgres了。

$ ssh db


$ psql -h localhost -p 5443 orders


$ pgadmin3 &


Host api
LocalForward 8080 localhost:80


$ ssh api


$ firefox http://localhost:8080/

15. 减少延迟


GSSAPIAuthentication no


16. 加速连接


Host dev
Ciphers arcfour



Posted in Uncategorized



我不要自我重复 — 这也许是在编程开发这最最基本的一个信条,就是要告诉你不要出现重复的代码。我们很多的编程结构之所以存在,就是为了帮助我们消除重复(例如,循环语句, 函数,类,等等)。一旦程序里开始有重复现象的出现(例如很长的表达式、一大堆的语句,但都是为了表达相同的概念),你就需要对代码进行一次新的提炼,抽 象。

提炼原则 — 跟“不要自我重复原则”相关,这一原则是说“程序中任何一段具有功能性的代码在源代码文件中应该唯一的存在。”

保持简单 — 简单化(避免复杂)永远都应该是你的头等目标。简单的程序让你写起来容易,产生的bug更少,更容易维护修改。

不要开发你目前用不到的功能 — 除非你真正需要用到它,否则不要轻易加上那些乱七八糟用不到的功能。

用最简单的方法让程序跑起来 — 在开发时有个非常好的问题你需要问问自己,“怎样才能最简单的让程序跑起来?”这能帮助我们在设计时让程序保持简单。

不要让我动脑子 — 这实际上是Steve Krug 关于web界面操作的一本书的书名,但也适用于编程。主旨是,程序代码应该让人们花最小的努力就能读懂和理解。如果一段程序对于阅读者来说需要花费太多的努力才能理解,那它很可能需要进一步简化。

开放/封闭原则 — 程序里的实体项(类,模块,函数等)应该对扩展行为开放,对修改行为关闭。换句话说,不要写允许别人修改的类,应该写能让人们扩展的类。

为维护者写程序 — 任何值得你编写的程序在将来都是值得你去维护的,也许由你维护,也许由他人。在将来,当你不得不维护这些程序时,你对这些代码的记忆会基本上跟一个陌生人 一样,所以,你最好还是当成一直在给别人写程序。一个有助于你记住这个原则的办法是“写程序时时刻记着,这个将来要维护你写的程序的人是一个有严重暴力倾 向,并且知道你住在哪里的精神变态者”。

最少意外原则 — 最少意外原则通常是使用在用户界面设计上,但这个原则同样适用于编写程序。程序代码应尽可能的不要让阅读者感到意外。也就是说应该遵循编码规范和常见习惯,按照公认的习惯方式进行组织和命名,不符常规的编程动作应该尽可能的避免。

单一职责原则 — 一个代码组件(例如类或函数)应该只执行单一的预设的任务。

最小化耦合关系 — 一个代码片段(代码块,函数,类等)应该最小化它对其它代码的依赖。这个目标通过尽可能少的使用共享变量来实现。“低耦合是一个计算机系统结构合理、设计优秀的标志,把它与高聚合特征联合起来,会对可读性和可维护性等重要目标的实现具有重要的意义。”

最大化内聚性 — 具有相似功能的代码应该放在同一个代码组件里。

隐藏实现细节 — 隐藏实现细节能最小化你在修改程序组件时产生的对那些使用这个组件的其它程序模块的影响。

笛米特法则(Law of Demeter) — 程序组件应该只跟它的直系亲属有关系(例如继承类,内包含的对象,通过参数入口传入的对象等。)

避免过早优化 — 只有当你的程序没有其它问题,只是比你预期的要慢时,你才能去考虑优化工作。只有当其它工作都做完后,你才能考虑优化问题,而且你只应该依据经验做法来优 化。“对于小幅度的性能改进都不该考虑,要优化就应该是97%的性能提升:过早优化是一切罪恶的根源”—Donald Knuth。

代码复用 — 这不是非常核心的原则,但它跟其它原则一样非常有价值。代码复用能提高程序的可靠性,节省你的开发时间。

职责分离 — 不同领域的功能应该由完全不同的代码模块来管理,尽量减少这样的模块之间的重叠。

拥抱变化 — 这是Kent Beck的一本书的副标题,它也是极限编程和敏捷开发方法的基本信条之一。很多的其它原则都基于此观念:面对变化,欢迎变化。事实上,一些经典的软件工程 原则,例如最小化耦合,就是为了让程序更容易面对变化。不论你是否采用了极限编程方法,这个原则对你的程序开发都有重要意义。

Posted in Uncategorized






Patrick McKenzie是美国一家小软件公司的老板,他写了一篇长文,介绍这个行业的一些实际情况。我看了以后很感慨,有些地方很受启发。我选择了一部分,翻译如下。




(90% of programming jobs are in creating Line of Business software)












(Engineers are hired to create business value, not to program things)










(Don’t call yourself a programmer)






正确的做法是,你应该把自己描述成与增加收入、降低成本有关系的人,比如”xx产品的开发者”或”改进者”。有一个Google Adsense程序员的自我介绍,是这样写的:”Google公司97%的收入,与我的代码有关。”




(You are not defined by your chosen software stack)








天才程序员是很少的,可是需要天才程序员的工作机会却很多很多,大多数场合都是需求远远大于供给。这意味着,即使你不是天才程序员,只要你是一个优 秀工程师,那些招聘公司也会立刻录用你,因为它们知道招聘到天才程序员的机会微乎其微。(重复一遍,所谓”优秀工程师”,就是你的履历上有一连串增加收 入、降低成本的记录。)






(How do I become better at negotiation?)














(Are startups great for your career as a fresh graduate?)










(So would you recommend working at a startup? )








(Your most important professional skill is communication)





Posted in Uncategorized


这里的大型网站架构只包括高互动性高交互性的数据型大型网站,基于大家众所周知的原因,我们就不谈新闻类和一些依靠HTML静态化就可以实现的架构 了,我们以高负载高数据交换高数据流动性的网站为例,比如海内,开心网等类似的web2.0系列架构。我们这里不讨论是PHP还是JSP或者.NET环 境,我们从架构的方面去看问题,实现语言方面并不是问题,语言的优势在于实现而不是好坏,不论你选择任何语言,架构都是必须要面对的。



众所周知,对于一些相对小的站点来说,数据量并不是很大,select和update就可以解决我们面对的问题,本身负载量不是很大,最多再加几个 索引就可以搞定。对于大型网站,每天的数据量可能就上百万,如果一个设计不好的多对多关系,在前期是没有任何问题的,但是随着用户的增长,数据量会是几何 级的增长的。在这个时候我们对于一个表的select和update的时候(还不说多表联合查询)的成本的非常高的。


在一些时候,2.0的CTO都有个尚方宝剑,就是缓存。对于缓存,在高并发高处理的时候也是个大问题。在整个应用程序下,缓存是全局共享的,然而在 我们进行修改的时候就,如果两个或者多个请求同时对缓存有更新的要求的情况下,应用程序会直接的死掉。这个时候,就需要一个好的数据并发处理策略以及缓存 策略。



对于一些支持文件上传的2.0的站点,在庆幸硬盘容量越来越大的时候我们更多的应该考虑的是文件应该如何被存储并且被有效的索引。常见的方案是对文 件按照日期和类型进行存贮。但是当文件量是海量的数据的情况下,如果一块硬盘存贮了500个G的琐碎文件,那么维护的时候和使用的时候磁盘的Io就是一个 巨大的问题,哪怕你的带宽足够,但是你的磁盘也未必响应过来。如果这个时候还涉及上传,磁盘很容易就over了。




我们可以很容易的规划出一个符合第三范式的数据库,里面布满了多对多关系,还能用GUID来替换INDENTIFY COLUMN 但是,多对多关系充斥的2.0时代,第三范式是第一个应该被抛弃的。必须有效的把多表联合查询降到最低。







成也AJAX,败也AJAX,AJAX成为了主流趋势,突然发现基于XMLHTTP的post和get是如此的容易。客户端get或者post 到服务器数据,服务器接到数据请求之后返回来,这是一个很正常的AJAX请求。但是在AJAX处理的时候,如果我们使用一个抓包工具的话,对数据返回和处 理是一目了然。对于一些计算量大的AJAX请求的话,我们可以构造一个发包机,很容易就可以把一个webserver干掉。


对于HTTP协议来说,数据包都是明文传输的,也许我们可以说我们可以用加密啊,但是对于G问题来说的话,加密的过程就可能是明文了(比如我们知道 的QQ,可以很容易的判断他的加密,并有效的写一个跟他一样的加密和解密方法出来的)。当你站点流量不是很大的时候没有人会在乎你,但是当你流量上来之 后,那么所谓的外挂,所谓的群发就会接踵而来(从qq一开始的群发可见端倪)。也许我们可以很的意的说,我们可以采用更高级别的判断甚至HTTPS来实 现,注意,当你做这些处理的时候付出的将是海量的database,io以及CPU的成本。对于一些群发,基本上是不可能的。笔者已经可以实现对于百度空 间和qq空间的群发了。大家愿意试试,实际上并不是很难。


当我们的一台databaseserver不堪重负的时候,这个时候我们就需要做基于数据库的负载和集群了。而这个时候可能是最让人困扰的的问题 了,数据基于网络传输根据数据库的设计的不同,数据延迟是很可怕的问题,也是不可避免的问题,这样的话,我们就需要通过另外的手段来保证在这延迟的几秒或 者更长的几分钟时间内,实现有效的交互。比如数据散列,分割,内容处理等等问题。


Openapi已经成为一个不可避免的趋势,从google,facebook,myspace到,都在考虑这个问题,它 可以更有效的留住用户并激发用户的更多的兴趣以及让更多的人帮助你做最有效的开发。这个时候一个有效的数据共享平台,数据开放平台就成为必不可少的途径 了,而在开放的接口的情况保证数据的安全性和性能,又是一个我们必须要认真思考的问题了。

Posted in Uncategorized

/usr 的来龙去脉

在 linux 文件结构中,有一个很神奇的目录 —— /usr。之前一直没有怎么关注过它,反正程序都是安装在里边的,也没有什么值得追根溯源的东西。直到有一天 fedora 要简化整个文件系统体系,看到讨论才想到,usr 到底是什么的缩写呢,它又是怎么来的呢?


  • usr 是 unix system resources 的缩写;
  • usr 是 user 的缩写;
  • usr 是 unix software resources 的缩写。

根据常识判断,是 user 缩写的可能性不大,因为和 /home 冲突了嘛。不过是 system resources 还是 software resources 的缩写还真不好说。特此查了好多东西,却发现竟然连 wikipedia 也模棱两可

后来终于找到了 相关的文档和介绍。(viacache

/usr usually contains by far the largest share of data on a system. Hence, this is one of the most important directories in the system as it contains all the user binaries, their documentation, libraries, header files, etc…. X and its supporting libraries can be found here. User programs like telnet, ftp, etc…. are also placed here. In the original Unix implementations, /usr was where the home directories of the users were placed (that is to say, /usr/someone was then the directory now known as /home/someone). In current Unices, /usr is where user-land programs and data (as opposed to ’system land’ programs and data) are. The name hasn’t changed, but it’s meaning has narrowed and lengthened from “everything user related” to “user usable programs and data”. As such, some people may now refer to this directory as meaning ‘User System Resources’ and not ‘user’ as was originally intended.(via1,2

/usr 是系统核心所在,包含了所有的共享文件。它是 unix 系统中最重要的目录之一,涵盖了二进制文件,各种文档,各种头文件,x,还有各种库文件;还有诸多程序,例如 ftp,telnet 等等。

曾经的 /usr 还是用户的家目录,存放着各种用户文件 —— 现在已经被 /home 取代了(例如 /usr/someone 已经改为 /home/someone)。现代的 /usr 只专门存放各种程序和数据,用户目录已经转移。虽然  /usr 名称未改,不过其含义已经从“用户目录”变成了“unix 系统资源”目录。值得注意的是,在一些 unix 系统上,仍然把 /usr/someone 当做用户家目录,如 Minix。

至此,真相大白。看来就像前一阵子的 /var/run 移到 /run 一样。

真的是不看不知道,一看吓一跳呀。原来 linux 几经进化,好多目录的诞生和用途已经产生了根本的变化。历史车轮在前进,长江后浪推前浪,正所谓:学习历史,收获真知;尽心竭力,前进不止。

附录:/usr 目录结构

  • /usr/bin : 所有可执行文件,如 gcc,firefox 等(指不包含在 /sbin 和 /bin 内的);
  • /usr/include : 各种头文件,编译文件等时需要使用;
    • /usr/include/’package-name’ : 程序特定的头文件;
  • /usr/lib : 所以可执行文件所需要的库文件;
  • /usr/local : /usr 通常只包含系统发行时自带的程序,而 /usr/local 则是本地系统管理员用来自由添加程序的目录;
  • /usr/X11R6 : x 系统的二进制文件,库文件,文档,字体等。它不等同于 /usr 的作用,只有 x 才能调用这些库文件等,其他程序不读取或者使用。因为 linux 没有原生图形界面,而且 linux 大部分情况下是 for server 的,所以图形界面没有意义;其中 X11R6 代表 version 11 release 6;
    • /usr/X11R6/bin : x 的二进制文件,包含运行 x 的必须文件;
    • /usr/X11R6/include : x 相关的头文件;
    • /usr/X11R6/lib : x 库文件;
    • /usr/X11R6/lib/modules : x 的模块,启动时加载。缺少 video4linux, DRI and GLX 和 输入输出设备 模块,将工作不正常;
    • /usr/X11R6/lib/X11/fonts : x font server 的字体文件;
  • /usr/doc : 文档。实际是 /usr/share/doc 的软链接;
  • /usr/etc : 一个极少用到的配置文件存放地;
  • /usr/games : 曾经包含游戏等文件,现在很少用到;
  • /usr/info : 系统相关信息,是 /usr/share/info 的软链接;
  • /usr/man : man 手册,已经移至 /usr/share/man
  • /usr/sbin : 类似 /sbin,root 可以执行。但此目录不包含在环境变量 $PATH 中,它包含的程序类似于 chroot, useradd, in.tftpd and pppconfig;
  • /usr/share : 它包含了各种程序间的共享文件,如字体,图标,文档等。(/usr/local 对应的目录是  /usr/loca/share);
    • /usr/share/doc : 类似应用程序的 man 手册。它包含程序的说明文件,默认配置文件等;
    • /usr/share/info : 不常用,已经被 man 代替;
    • /usr/share/man : app 的 manual;
    • /usr/share/icons : 应用程序的图标等文件,分为 png,svg 等多种格式;
    • /usr/share/fonts : 字体文件,系统范围内可使用,~/.fonts 仅当前用户可用;
  • /usr/src : linux 内核的源码和说明文档等;
    • /usr/src/linux : linux 源代码;
    • /usr/src/linux/.config : 内核编译过程产生的文件;通常由命令 ‘make config’ , ‘make menuconfig’ 或 ‘make xconfig’ 执行后产生;
    • /usr/src/linux/.depend, /usr/src/linux/.hdepend : ‘make dep’ 检测编译依赖时需要的文件,由 /usr/src/linux/.config 产生;
    • /usr/src/linux/COPYING : GNU license;
    • /usr/src/linux/Makefile : 编译内核所需的 Makefile;
    • /usr/src/linux/Rules.make : 当有多个 Makefile 时,根据它的规则执行 make;
  • /usr/tmp : 已经被众多发行版抛弃的临时文件夹。
Posted in Uncategorized

ruby-debug in 30 seconds (we don't need no stinkin' GUI!)

Many people (including me) have complained about the lack of a good GUI debugger for Ruby. Now that some are finally getting usable, I've found I actually prefer IRB-style ruby-debug to a GUI.

There’s good tutorial links on the ruby-debug homepage, and a very good Cheat sheet, but I wanted to give a bare-bones HOWTO to help you get immediately productive with ruby-debug.

Install the latest gem

$ gem install ruby-debug 

Install the cheatsheet

$ gem install cheat $ cheat rdebug 

Set autolist, autoeval, and autoreload as defaults

$ vi ~/.rdebugrc set autolist set autoeval set autoreload 

Run Rails (or other app) via rdebug

$ rdebug script/server 

Breakpoint from rdebug

(rdb:1) b app/controllers/my_controller.rb:10 

Breakpoint in source

require 'ruby-debug' debugger my_buggy_method('foo') 


(rdb:1) cat RuntimeError 

Continue to breakpoint

(rdb:1) c 

Next Line (Step Over)

(rdb:1) n 

Step Into

(rdb:1) s 


(rdb:1) c 

Where (Display Frame / Call Stack)

(rdb:1) where 

List current line

(rdb:1) l= 

Evaluate any var or expression

(rdb:1) myvar.class 

Modify a var

(rdb:1) @myvar = 'foo' 


(rdb:1) h 

There are many other commands, but these are the basics you need to poke around. Check the Cheat sheet for details.

This can also be used directly from any IDE that supports input into a running console (such as Intellij Idea).

That should get you started. So, before you stick in another ‘p’ to debug, try out ruby-debug instead!

require 'rubygems'
require 'ruby-debug'
#$ruby breakpoint_test.rb
#vim breakpoint_test.rb
#:!ruby breakpoint_test.rb
#Next Line (Step Over)
#(rdb:1) n
#Step Into
#(rdb:1) s
#to debug in a function which is called from other place,before this function call,type 's' and you will found your are inside this function.
def leap_year year
leap = case
when year % 400 == 0: true
when year % 100 == 0: false
else year % 4 ==0
puts leap
if __FILE__ == $0
# tests...
puts "year=2000"
leap_year 2000
puts "year=2004"
leap_year 2004
puts "year=2002"
leap_year 2002

标签: breakpoint debug rails ruby shell

Posted in Uncategorized