Skip to content

Instantly share code, notes, and snippets.

@hinagiku
Forked from nightire/Changes in Rails 4_1.md
Created April 21, 2013 07:13
Show Gist options
  • Select an option

  • Save hinagiku/5428756 to your computer and use it in GitHub Desktop.

Select an option

Save hinagiku/5428756 to your computer and use it in GitHub Desktop.

Routes

小心地使用 Match(Rails 3 已实现)

Rails 3 提供了 match 方法供我们自定义 routes,然而我们要小心使用它以避免“跨站脚本攻击”(XSS Attack)。比如像这样的 routes:

注:(r3 代表 Rails 3,r4 代表 Rails 4)

# routes.rb
match '/books/:id?purchase', to: 'books@purchase'

用户可以很轻松地使用 XSS Attack,比如使用这样一个链接:

<a href="http://yoursite.com/books/4/purchase">Get It Free!</a>

你绝对不想看到这种情况,所以你要限制客户端可以访问此资源的方式。例如:

match '/books/:id?purchase', to: 'books@purchase', via: :post # :all 代表匹配所有的 HTTP methods

# 或者
post '/books/:id?purchase', to: 'books@purchase'

否则你就会收到如下错误提示:

You should not use the match method in your router without specifying an HTTP method. (RuntimeError)


新的 HTTP Verb:patch

过去我们使用 put 来完成对资源的更新请求,然而 put 本身是对整个资源(数据集合)进行更新,若要实现部分资源的更新(单个数据,或是几个产生变化的数据实体),put 就有点过重了,此时 patch 会更加合适。

patch 并不是什么新东西,此前就一直存在于 HTTP 1.1 协议规范之中,只不过这一次 Rails 4 把它正式的引入进来。在 Rails 4 中,putpatch 都指向 controller#update,在更新部分资源时(比如 @book)会使用 patch,生成类似下例中的页面元素:

<form action="/books/20" method="post">
  <div style="margin:0;padding:0;display:inline">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="_method" type="hidden" value="patch" /> <!-- 关键就是这一行了 -->
  </div>
</form>

同时还增加了一个 #patch 方法,可以在合适的时候使用:

test "update book with PATCH verb" do
  patch :update, id: @book, book: { title: @book.title }
  assert_redirected_to book_url(@book)
end

Concerns for Routing

Concerns(关注点)是一种组织代码结构的方式,用来帮助开发者将复杂的逻辑和重复代码梳理清楚,我们在 Rails 4 中多次看到对于 Concerns 的设计和实现。先看一段老代码:

resources :messages do
  resources :comments
  resources :categories
  resources :tags
end

resources :posts do
  resources :comments
  resources :categories
  resources :tags
end

resources :articles do
  resources :comments
  resources :categories
  resources :tags
end

像这样的代码存在许多的重复,Rails 4 允许我们重构它:

concern :sociable do
  resources :comments
  resources :categories
  resources :tags
end

resources :messages, concerns: :sociable
resources :posts, concerns: :sociable
resources :articles, concerns: :sociable

可以通过传递参数来实现对个例的特化:

concern :sociable do |options|
  resources :comments, options
  resources :categories, options
  resources :tags, options
end

resources :messages, concerns: :sociable
resources :posts, concerns: :sociable
resources :articles do
  concerns :sociable, only: :create
end

甚至我们可以抽取出来变成单独的类:

# app/concerns/sociable.rb
class Sociable
  def self.call(mapper, options)
    mapper.resources :comments, options
    mapper.resources :categories, options
    mapper.resources :tags, options
  end
end

# config/routes.rb
concern :sociable, Sociable

resources :messages, concerns: :sociable
resources :posts, concerns: :sociable
resources :articles do
  concerns :sociable, only: :create
end

抛弃 Ruby 1.8.x

我们都听说 Rails 4 需要 Ruby 的版本不能小于 1.9.3,不过这一点所引起的变化通常都十分微妙,不容易让人注意到。

聒噪的 nil

1.8.x 时代,nil.id 是合法的(一切都是对象!),但是不合理,经常惹人厌。于是 1.9.2 之后,逐渐使用 object_id 来代替,使用旧的 id 方法会抛出运行时错误:

RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id

Rails 3 无法永远摆脱这恼人的提示,因为它要同时兼容 1.8 和 1.9,于是一旦碰上可能会出现的 nil.id 就会看到上面那个错误

在 Rails 4 的世界里,手起刀落,喀嚓~~~ 从此 nil 不再聒噪,世界终于清净了……

NoMethodError: undefined method `id' for nil:NilClass

线程安全

线程安全的处理在 Rails 3 中已有,不过默认是关闭的:

# config/environments/production.rb
MyApp::Application.configure do
  # Enable threaded mode
  # config.threadsafe!
end

这个方法在 Rails 4 中不推荐使用,新的线程安全机制在默认情况下就已经开启:

# config/environments/production.rb
MyApp::Application.configure do
  config.cache_classes = true # 阻止类在请求中重新载入,并保证 Rack::Lock 不包含在中间件堆栈中
  config.eager_load = true # 在新线程创建前加载全部代码
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment