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
- Những middleware tối thiếu để có thể chạy API server sẽ được load.
- ApplicationController sẽ thừa kế ActionController::API
- 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.