- vừa được xem lúc

ActiveSupport: Có thể bạn chưa biết?

0 0 11

Người đăng: LamDN

Theo Viblo Asia

Trong quá trình làm việc với Ruby on Rails, khi gặp phải vấn đề đặc biệt cần giải quyết, nếu như không tìm hiểu kỹ, ta sẽ dễ tự tay xây dựng và giải quyết mọi thứ trong khi bản thân framework đã có sẵn những công cụ hỗ trợ cho vấn đề đó. Vì vậy thay miệt mài tìm giải pháp, hãy lướt qua ActiveSupport một lượt, rất có thể bạn sẽ tìm được ngay thứ mà mình cần.

ActiveSupport::CurrentAttributes

Với những trang web hỗ trợ authetication, nhất là khi sử dụng gem devise bạn sẽ bắt gặp current_user ở khắp nơi trong view hoặc controller. Có một vấn đề là current_user không khả dụng ở trong các models hay services…Lúc này ActiveSupport::CurrentAttributes có thể là một giải pháp dành cho bạn.

Theo định nghĩa, đây là một abstract class hỗ trợ singleton attribute cô lập theo thread. Nghĩa là nếu mỗi request được xử lý bởi một thread, thì bạn có thể truy cập attribute đó ở khắp mọi nơi đến khi request kết thúc. Trở lại với ví dụ trên, ta hãy so sánh trước và sau khi sử dụng current attributes:

  • Trước khi sử dụng:
# app/presenters/post_presenter.rb class PostPresenter def initialize post, user @post = post @user = user end def current_user_post? @post.user.eql?(@user) end
end

Khi trả dữ liệu cho API:

# app/controllers/posts_controller.rb def show @presenter = PostPresenter.new(@post, current_user)
end
  • Sau khi sử dụng:
class Current < ActiveSupport::CurrentAttributes attribute :user
end
# app/controllers/application_controller.rb before_action :set_current_user def set_current_user Current.user = current_user
end
# app/presenters/post_presenter.rb class PostPresenter def initialize post @post = post end def current_user_post? @post.user.eql?(Current.user) end
end
# app/controllers/user_controller.rb def show @presenter = PostPresenter.new(@post)
end

Với những logic phức tạp, nhiều tầng code, đồng nghĩa với việc bạn phải truyền current_user vào sâu bên trong, lúc đó bạn sẽ thấy được lợi ích từ việc sử dụng current attributes. Tuy nhiên, tính năng này chỉ có từ phiên bản Rails 5.2 trở lên.

ActiveSupport::Subscriber

Nếu như đã từng làm việc với Javascript, chắc bạn cũng không lạ gì với việc đăng ký và trigger sự kiện của một DOM. Rails cũng cung cấp một cơ chế tương tự như vậy và nó chính là ActiveSupport::Subscriber. Trong quá trình chạy, Rails trigger rất nhiều sự kiện, ví dụ như:

  • start_processing.action_controller: Trigger khi bắt đầu process controller action .
  • process_action.action_controller: Trigger sau khi đã process xong một action.
  • sql.active_record: Trigger sau khi ActiveRecord chạy một câu sql.

Và còn nhiều event khác nữa. Nhưng chúng ta có thể dùng nó vào việc gì

Bạn có thể sử dụng nó vào việc monitoring hệ thống. Hãy cùng xem qua ví dụ dưới đây:

module Monitoring class QuerySubscriber < ActiveSupport::Subscriber IGNORE_NAMES = ["SCHEMA", "EXPLAIN"] SLOW_TIME = 1000 def sql event return if event.duration <= SLOW_TIME payload_name = event.payload[:name] return if payload_name.blank? || IGNORE_NAMES.include?(payload_name) event_data = event.payload.slice(:name, :sql) report_slow_query(event_data) end private def report_slow_quary event_data Slack.push_message(:slow_query, event_data) end end
end Monitoring::QuerySubscriber.attach_to(:active_record)

Ở trên, chúng ta đăng ký một subscriber lắng nghe sự kiện sql.active_record. Với mỗi câu query được chạy, ta sẽ kiểm tra thời gian thực thi và report nếu như nó vượt quá 1s.

Bạn cũng có thể trigger event của riêng mình bằng việc sử dụng [ActiveSupport::Notifications](https://github.com/rails/rails/blob/5-2-stable/activesupport/lib/active_support/notifications.rb) với cơ chế tương tự.

ActiveSupport::Callbacks

Với notifications hay subscribers, chúng sẽ được trigger tại một thời điểm thường là khi bắt đầu hay kết thúc một hành động nào đó. Callbacks cũng có phần tương đồng nhưng phạm vi của nó chỉ trong life cycle của một object. Ví dụ khi publish một bài post, bạn cần gửi notification cho followers, lúc này bạn nên sử dụng ActiveSupport::Notifications. Còn nếu bạn cần tự động set description cho bài post trước khi nó được save thì đó là lúc bạn nên dùng callback.

Ngoài những callbacks mặc định của Rails, bạn có thể tự đăng ký callback bằng cách sử dụng ActiveSupport::Callbacks. Hãy xem ví dụ dưới đây:

class Post include ActiveSupport::Callbacks define_callbacks :publish def make_publish run_callbacks :publish do puts "Publish post" end end set_callback :publish, :before, :log_before_publish def log_before_publish puts "Log before publish" end set_callback :publish, :after do |post| puts "Log after publish ID: #{post.object_id}" end
end

Để define callbacks bạn cần làm các bước sau:

  • Khai báo event nào trong object sẽ hỗ trợ callbacks thông qua define_callbacks.
  • Cài đặt callbacks của events thông qua set_callback. Bạn có thể sử dụng instance method hoặc đơn giản là hơn là một Proc hay lambda. Các timming hỗ trợ bao gồm before, arroundafter.
  • Chạy các callback đã được đăng ký với events thông qua run_callbacks.
post = Post.new
post.make_publish

Output:

Log before publish
Publish post
Log after publish ID: 2379297800

ActiveSupport::StringInquirer

Đây là cách bạn có thể sử dụng để làm cho việc kiểm tra string trở nên dễ dàng và trong sáng hơn. Hãy xem ví dụ sau:

class Media def initialize type @type = type. end def text? @type == "text" end def image? @type == "image" end def video? @type == "photo" end
end
media = Media.new("image") media.image? # => true
media.text? # => false

Nhưng với ActiveSupport::StringInquirer mọi thứ sẽ đơn giản hơn rất nhiều:

class Media def initialize type @type = ActiveSupport::StringInquirer.new(type) end delegate :text?, :image?, :video?, to: :@type
end
media = Media.new("image") media.image? # => true
media.text? # => false

ActiveSupport::Duration

Khi bạn muốn xử lý các vấn đề liên quan đến một khoảng thời gian như countdown event, hiển thị deadline… ActiveSupport::Duration sẽ là điều đầu tiên bạn nên nghĩ đến. Nó hỗ trợ hầu hết các yêu cầu của bạn liên quan đến durration.

  • Bạn có thể hiển thị durration:
ActiveSupport::Duration.build(400.days) # => 1 year, 1 month, 4 days, 7 hours, 41 minutes, and 42.0 seconds
  • Nếu muốn lấy thông tin của durration:
ActiveSupport::Duration.build(400.days).parts # => {:years=>1, :months=>1, :days=>4, :hours=>7, :minutes=>41, :seconds=>42.0}

Conclusion

Bản thân Rails đã hỗ trợ hầu hết các tính năng cần thiết cho việc phát triển một trang web cơ bản. Do đó, ứng dụng của ActiveSupport đôi khi bị lãng quên. Vì thế, nếu như gặp phải vấn đề với những hỗ trợ mặc định của Rails, bạn hãy tìm sự trợ giúp của ActiveSupport trước khi bắt tay vào xử lý mọi thứ.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tôi cá là bạn không biết những điều này - Ruby on rails ( Phần 2)

Các bạn có thể theo dõi phần 1 ở đây :. https://viblo.asia/p/toi-ca-la-ban-khong-biet-nhung-dieu-nay-ruby-on-rails-phan-1-WAyK8DDeKxX. 5.

0 0 211

- vừa được xem lúc

Rails Memoization

Memoization is a process that can be used to speed up rails methods. It caches the results of methods that do time-consuming work, work that only needs to be done once. Here is an example. Example.

0 0 34

- vừa được xem lúc

Tại sao Rails lại dùng cả Webpack lẫn Sprocket?

Khi Rails 6 được ra mắt, có thể bạn đã từng tự hỏi. WTF, sao Webpack đã được add vào rồi, mà Sprocket vẫn tồn tại thế kia . Chẳng phải Webpack và Sprocket được dùng để giải quyết chung một công việc hay sao. Hoặc cả đây:.

0 0 47

- vừa được xem lúc

Bạn nên sử dụng Elasticsearch trong ứng dụng Ruby On Rails như thế nào?

Elasticsearch là một công cụ phân tích và mã nguồn mở mạnh mẽ và linh hoạt, phân tán, theo thời gian thực. Đó là tiêu chuẩn vàng trong công nghệ tìm kiếm.

0 0 70

- vừa được xem lúc

Form object pattern trong rails

1.Mở đầu.

0 0 100

- vừa được xem lúc

Sử dụng Twilio để gửi SMS trong ứng dụng Ruby on Rails

Ngoài cách xác nhận tài khoản hay gửi thông báo bằng email thì hôm nay mình sẽ hướng dẫn các bạn 1 cách nữa là thông qua SMS/Voice. Công cụ sử dụng sẽ là gem Twilio. Installation. Để cài đặt bằng Bundler, hãy lấy phiên bản mới nhất:.

0 0 56