1
1

More than 5 years have passed since last update.

拥抱 Rails 4_1

Last updated at Posted at 2013-03-23

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 CSRF Attack,比如使用这样一个链接:

CodeSchool 的 Rail 4 教程里写的是 XSS Attack,经查证和问询,证明这是 CodeSchool 的失误,应该会很快改正过来,再次先做一个修正,并向受到误导的朋友致歉

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

这会使用 GET 去请求这个资源,你绝对不想看到这种情况(你希望的是 POST),所以你要限制客户端可以访问此资源的方式。例如:

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
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1