`

关于Rails 2.3 十件你应该知道的事

阅读更多
首先,这个是一篇粉饰Rails2.3的文章,挑选了十个方面展示Rails2.3的改进.

1. Rails在Development的模式下启动更快.

这是个所有程序员都会感激的事,在development模式下rails使用lazy加载的方式启动.大幅度的提升了启动速度.
使用空的工程文件,可以得到如下的真是数据对比:

引用
script/server -d:

Rails 2.2: 1.461s
Rails 2.3: 0.869s


当然,真实环境一定会比这个值要慢毕竟这里没有加载任何依赖的类库.

2. 官方对于Rails Engines支持

得益于Merb的slices方法的实现,Rails将官方支持Engines到rails核心.Engines可以有自己的models,views和自己的routes,在之前,Engines一直都是以插件存在,这样就是往往,会遇到rails不版本的不支持的问题.

Rails Engines有一些很棒的功能,请查看Rails Engines网站参考.

3. Routing 的提升

RESTful routes 现在将使用更少的内存,因为类似formatted_*的路由将不再生成,这意味这将节省大概50%的内存
如果,有如下router:

map.resources :users

如果你希望读取XML格式版的user资源,那么你将:

user_path(123, :format => 'xml')


在Rails2.3 only和except 选项将不允许在嵌套路由使用,因为之前的功能会导致误解.

map.resources :users, :only => [:index, :new, :create] do |user|
  # now will generate all the routes for hobbies
  user.resources :hobbies
end


4. JSON 功能的提升

在ActiveSupport::JSON中,如下功能得到提升:

to_json 在JSON spec改进了引号使用
Before:

{123 => 'abc'}.to_json
=> '{123: "abc"}'

Now:

{123 => 'abc'}.to_json
=> '{"123": "abc"}'


加强了对Unicode字符的处理,不会显示乱码
Before:

ActiveSupport::JSON.decode("{'hello': 'fa\\u00e7ade'}")
=> {"hello"=>"fa\\u00e7ade"}

Now:

ActiveSupport::JSON.decode("{'hello': 'fa\u00e7ade'}")
=> {"hello"=>"façade"}


5. Default scopes功能

在Rails2.3之前的版本理,如果,你在执行find的时候,没有附加选项,你将得到一个没有任何排序,或限制的的查询.现在,在Rails2.3上你可以通过Default scopes来使用这样的功能,演示代码如下:

class User < ActiveRecord::Base
  default_scope :order => '`users`.name asc'
end


Default的scope会被任何的定制选项覆盖.

User.all # 将使用默认scope
User.all(:order => 'name desc') # 将会按照name降序输出.


Example:

User.create(:name => 'George')
User.create(:name => 'Bob')
User.create(:name => 'Alice')

puts User.all.map { |u| "#{u.id} - #{u.name}" }

3 - Alice
2 - Bob
1 - George


6. 嵌套的事务执行

传递
 :requires_new => true 
给 ActiveRecord::Base
就可以创建一个嵌套的事务处理
User.transaction do
  user1 = User.create(:name => "Alice")

  User.transaction(:requires_new => true) do
    user2 = User.create(:name => "Bob")
   end
end


7. Asset Host Objects

自从Rails2.1开始,就可以配置Rails使用asset_host这个Proc,例如,一些浏览器不允许SSl请求从不安全的源加载images文件.如果,想要保证SSL始终从相同的host请求,可以如下:

	

ActionController::Base.asset_host = Proc.new { |source, request|
  if request.ssl?
    "#{request.protocol}#{request.host_with_port}"
  else
    "#{request.protocol}assets.example.com"
  end
}

Rails2.3中会如下处理,以便不会显得混乱:

class SslAssetHost
  def call(source, request)
    if request.ssl?
      "#{request.protocol}#{request.host_with_port}"
    else
      "#{request.protocol}assets.example.com"
    end
  end
end

ActionController::Base.asset_host = SslAssetHost.new


8. 更容易的更新Rails timestamp字段

如果,你希望试图更新Rails自动生成的timestamp字段,例如:created_at和update_at, 你会发现这是件相当痛苦的事,因为,在Rails2.3之前,这是没有考虑可以允许的.
现在,你可以通过类似,如下的代码,更新这个字段:
User.create(:name => "Alice", :created_at => 3.weeks.ago, :updated_at => 2.weeks.ago)

=> #<User id: 3, name: "Alice", created_at: "2009-03-08 00:06:58", updated_at: "2009-03-15 00:06:58">


那么,相同的如果,你不希望你的用户,修改这个字段,那么记着把这个字段,标记成attr_protected.

9. 嵌套属性和表单

这个改进,可以大幅度的改进复杂表单的描述和处理复杂对象.
首先,嵌套属性可以允许父对象代理授权子对象


class User < ActiveRecord::Base
 has_many :hobbies, :dependent => :destroy

  accepts_nested_attributes_for :hobbies
end

User.create(:name => 'Stan', 
            :hobbies_attributes => [{:name => 'Water skiing'}
                                    {:name => 'Hiking'}])


很简洁的,这将保存父对象和它关联models,如果,有错误,它们都不会被保存.

使用 FormBuilder实例的 fields_for方法, 表单可以出复杂的对象,示例如下:

	

<% form_for(@user) do |f| %>
  <div>
    <%= f.label :name, "User name:" %>
    <%= f.text_field :name %>
  </div>

  <div>
    <h2>Hobbies</h2>

    <% f.fields_for(:hobbies) do |hf| %>
      <div>
  <%= hf.label :name, "Hobby name:" %>
  <%= hf.text_field :name %>
      </div>
      <% end %>
  </div>

  <%= f.submit 'Create' %>
<% end %>


class UsersController < ApplicationController
  def new
    # In this contrived example, I create 3 dummy objects so I'll get
    # 3 blank form fields.
    @user = User.new
    @user.hobbies.build
    @user.hobbies.build
    @user.hobbies.build
  end
end



10. Rails Metal

You can now write very simple Rack endpoints for highly trafficked routes, like an API. These are slotted in before Rails picks up the route.

A Metal endpoint is any class that conforms to the Rack spec (i.e., it has a call method that takes an environment and returns the an array of status code, headers, and content).

Put your class in app/metal (not generated by default). Return a 404 response code for any requests you don’t want to handle. These will get passed on to Rails.

There’s a generator you can use to create an example Metal end point:

script/generate metal classname


In my sample app, I have what I would consider the “minimally useful” Rails Metal endpoint. It responds to /users.js and returns the list of users as JSON.

class UsersApi
  def self.call(env)
    # if this path was /users.js, reply with the list of users
    if env['PATH_INFO'] =~ /^\/users.js/
      [200, {'Content-Type' => 'application/json'}, User.all.to_json]
    else
      # otherwise, bail out with a 404 and let Rails handle the request
      [404, {'Content-Type' => 'text/html'}, 'not found']
    end
  end
end

If you want a little bit more help, you can use any other Rack-based framework, for example Sinatra.

For more details on how Rails Metal works, check out Jesse Newland’s article about it.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics