12/08/2018, 13:24

Những điểm thay đổi và chức năng mới cần biết về Rails 5

Source 今から知っておきたいRails 5の新機能・変更点 - ryohashimoto Background Anh chàng 1 năm trước còn ngồi hì hục code rails 8 tiếng mỗi ngày, 1 năm trở lại đây chuyển sang iOS và Android và không động tới 1 dòng code - I am Minh. Gần đây tôi được tham gia lead 1 dự án rails và những kỉ niệm ngọt ngào 1 năm ...

Source

今から知っておきたいRails 5の新機能・変更点 - ryohashimoto

Background

Anh chàng 1 năm trước còn ngồi hì hục code rails 8 tiếng mỗi ngày, 1 năm trở lại đây chuyển sang iOS và Android và không động tới 1 dòng code - I am Minh.

Gần đây tôi được tham gia lead 1 dự án rails và những kỉ niệm ngọt ngào 1 năm trước lại trở về quanh đây. Nhớ ngày ấy, những tin đồn về sự ra mắt của Rails 5, còn hì hục cãi nhau với khách hàng bảo không cần nâng cấp lên bản Rails 4 mới hơn đâu, cứ chờ 5 ra rồi làm một thể. Giờ thì trang web đó cũng không còn nữa, nhưng bản Rails 5 đáng trông đợi ngày nào cũng đã ra đời.

Thật tuyệt vời ^^!!!

Đầu tiên

Trước khi Ruby 2.3 ra mắt, bản beta của rails 5.0 đã chính thức được phát hành.

Cùng với việc Rails 5 sẽ có chức năng mới phục vụ cho WebSocket server cũng như JSON API server, đã có rất nhiều thay đổi lớn phía trong để có thể chạy trên phiên bản Ruby 2.2.2 trở lên. Ngoài ra, có rất nhiều các điểm thay đổi lớn được cho vào như model được kế thừa từ ApplicationRecord hay có thể chạy Rake task bằng rails command.

Ở bài viết này, tôi sẽ dựa trên lịch sử pull requests và issues của rails project trên gihub để giới thiệu về các điểm thay đổi cũng như chức năng mới của Rails 5.

Chức năng mới

Rails API

Thay vì ActionController::Base, bằng việc kế thừa ActionController::API ở controller đã giúp việc cấu trúc một Rails app nhẹ dành cho JSON API server thành công.

Trong trường hợp muốn tạo Rails app chỉ hoàn toàn cho API, hãy chỉ định option --api với rails new

$ rails new my_api --api

Sau đó sẽ có những xử lý như sau được thực hiện ở phía bên trong

  1. Những middleware tối thiếu để có thể chạy API server sẽ được load.
  2. ApplicationController sẽ thừa kế ActionController::API
  3. Không thực hiện việc tạo view cũng như asset của generator.

Nếu muốn chuyển rails app đang có thành dạng chỉ có API không thôi hãy tham khảo bài dưới đây.

Rails API to Be Part of Rails 5

Action Cable

Bằng việc sử dụng Action Cable sẽ giúp chúng ta thêm chức năng của WebSocket (truyền tin song phương realtime) vào Rails app một cách dễ dàng. Action Cable có cả chức năng của server lẫn client.

Ở phía server sử dụng class ApplicationCable::Connection và ApplicationCable::Channel.. để implement, còn bên client dựa vào App.cable.subscriptions.create của CoffeeScript(JavaScript) để gọi method AppearanceChannel#subscribed bên server.

Có thể tạo code của cả 2 bên server và client bằng generator. Dưới đây là ví dụ tạo channel tên là chat.

$ rails generate channel chat

Hãy tham khảo tại đây để biết thêm chi tiết về sample code này.

rails/actioncable

Có thể chạy rake task từ rails command

Đã có thể thực hiện các loại task chạy bằng rake command bằng rails command.

Ví dụ, migrate DB có thể chạy bằng rails db:migrate, hay việc confirm routing bằng rails routes.

Implement rake proxy for rails cli

Turbolinks 5

Bằng việc gán data-turbolinks-permanent vào DOM element sẽ giúp duy trì được giữa các trang và tránh được việc khởi tạo trạng thái lại và nâng cao được tốc độ.

Với những element cố định giữa các trang ví dụ như sidebar hãy gắn data-turbolinks-permanent, những element không giữ qua các trang hãy gắn data-turbolinks-temporary.

<div id="nav" data-turbolinks-permanent></div>
<div id="footer" data-turbolinks-temporary></div>

rails/turbolinks

Support Sprockets 3

Cho tới bản Rails 4 cần chỉ định có precompile asset nào trong file config/initializers/assets.rb, tuy nhiên tại Rails 5 thì có thể chỉ định tại file manifest.js ở directory app/assets/config/.

Ở trạng thái khởi tạo app thì file manifest.js sẽ như dưới đây:

//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css

(Tại trang tham khảo dưới đây đang là Sprockets 4, tuy nhiên hiện nay vẫn đang chỉ là Sprockets 3 mà thôi)

Rails 5: The Sprockets 4 Manifest

ActiveRecord::Attributes

Bằng việc chỉ định thuộc tính tại attribute của model, chúng ta có thể customize phương thức lấy thuộc tính của model bằng SQL hay truyền vào method where của ActiveRecord::Relation.

Với ví dụ dưới đây, bằng việc chỉ định integer với attribute có thuộc tính được định nghĩa là decimal trong DB

create_table :store_listings, force: true do |t|
  t.decimal :price_in_cents
end

chúng ta có thể convert được về dạng số nguyên.

class StoreListing < ActiveRecord::Base
  attribute :price_in_cents, :integer
end

Có sự khác biệt như dưới đây với trước và sau khi convert bằng attribute.

# before
store_listing.price_in_cents
=> BigDecimal.new(10.1)
# after
store_listing.price_in_cents
=> 10

Chi tiết hãy tham khảo link dưới đây.

ActiveRecord::Attributes::ClassMethods

Thêm các method liên quan tới query (#or, #left_outer_joins, #left_joins)

Method #left_outer_joins thực hiện kết hợp ngoài và #or có thể chỉ định điều kiện OR bằng SQL đã được thêm vào ActiveRecord::Relation.

Post.where('id = 1').or(Post.where('id = 2'))
=> SELECT * FROM posts WHERE (id = 1) OR (id = 2)
User.left_outer_joins(:posts)
=> SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"

Ngoài ra, alias #left_joins của #left_outer_joins cũng được thêm vào.

Added #or to ActiveRecord::Relation

added ActiveRecord::Relation#outer_joins

Thêm #pluck và #without vào module Enumerable

Đã có thể sử dụng hoạt động giống với method #pluck (chuyển column của record nhất định sang array) đối với hash array.

[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
=> ["David", "Rafael", "Aaron"]

Thêm nữa, method #without loại bỏ element nhất định trong array cũng đã được thêm vào.

people = ["David", "Rafael", "Aaron", "Todd"]
people.without "Aaron", "Todd"
=> ["David", "Rafael"]

Add Enumerable#pluck

Add Enumerable#without

Thêm option touch vào #save của ActiveRecord

Khi lưu record, nếu truyền touch: false vào option của method #save sẽ giúp chúng ta không làm thay đổi timestamp.

Tại ví dụ dưới đây, sau khi thay đổi data của model object article, giá trị updated_at không bị thay đổi.

updated_at = article
artile.save!(touch: false)
article.update_at == updated_at
=> true

Provide :touch option to save() to accommodate saving without updating timestamps

Thêm method ActiveRecord::Relation#in_batches

ActiveRecord#find_in_batches (thực hiện xử lý đối với model có số lượng data rất lớn) truyền array vào block hay truyền record, thì method ActiveRecord#in_bathces có thể truyền ActiveRecord::Relation vào block. Nếu truyền of vào option thì có thể thay đổi batch size.(default: 1000)

Person.in_batches.each_record(&:party_all_night!)
Person.in_batches.update_all(awesome: true)
Person.in_batches.delete_all
Person.in_batches.each do |relation|
  relation.delete_all
  sleep 10 # Throttles the delete queries
end

in_batches using ids

Điểm thay đổi

Nếu nơi tham chiếu của belongs_to mà nil sẽ sinh validation error

Để back về hoạt động như trước bản Rails 4, cần chỉ định optional: true tại belongs_to option.

belongs_to should default to required: true

Model ActiveRecord kế thừa ApplicationRecord

Tại bản Rails 5, nếu đã tạo app mới thì file app/models/application_record.rb sẽ được tạo ra như dưới đây và khi tạo model khác nữa thì sẽ không phải kế thừa từ ActiveRecord::Base mà từ ApplicationRecord

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

Từ trước tới nay, nếu muốn thêm chức năng vào toàn thể model của app thì cần thực hiện monkeypatch vào ActiveRecord::Base hoặc cần include module, tuy nhiên từ Rails 5 chỉ cần thêm method và ApplicationRecord là ok.

Introduce ApplicationRecord, an Active Record layer supertype

Job của ActiveJob cũng kế thừa ApplicationJob

ActiveJob cũng giống vậy, các job không phải kế thừa ActiveJob::Base nữa mà sẽ thực hiện kế thừa ApplicationJob ở file app/jobs/application_job.rb.

class ApplicationJob < ActiveJob::Base
end

Add explicit base class for ActiveJob jobs

ActionController::Parameters khong kế thừa hash nữa

Từ trước tới nay Parameters kế thừa ActiveSupport::HashWithIndifferentAccess, do có mối nguy hiểm rằng có thể tương tác với các parameter chưa được cấp phép tại các method của module Enumerable nên đã có một số thay đổi. (Nếu đang sử dụng method hash.. sẵn có, cần chú ý khi upgrade)

Make AC::Parameters not inherited from Hash

Bỏ khuyến khích sử dụng alias_method_chain

Rails 5 sử dụng Ruby 2.2.2 trở lên cho nên thay vì alias_method_chain của ActiveSupport, sử dụng Module #prepend của Ruby.

Rails 5, Module#prepend, and the End of alias_method_chain

Tổng kết

Rails 5 đã mở rộng tầm của app với Rails API và Action Cable.., ngoài ra đã gãi đúng chỗ ngứa với việc thêm các method query thuận tiện. Hiện nay đã có phiên bản beta với Rails 5, cho nên các bạn có thể thử nghiệm chức năng mới hay thử upgrade từ phiên bản 4 lên xem thử. Tiến lên !!!

Trang tham khảo

rails/rails

Rails 5.0.0.beta1: Action Cable, API mode, Rails command

This week in Rails: Rails 5 - The Beta Awakens

Cảm ơn các bạn đã xem bài.

0