0

Cách dùng một class để refer config var

Như chúng ta đều biết thì ở hầu hết các app có một class để refer đến những thuộc tính được setup sẵn, ví dụ: thông tin về Database, Email, Environment, ... Thông thường tất cả những thông tin đó được store vào một file yaml và được class này đọc, nhưng trong bài viết này mình sẽ hard code luôn cho dễ hiểu.

Đầu tiên mình viết một class:

module MusicGuu
  class Configuration
    def hot_trends
      @top ||= {
        top_hit: "See you again"
      }
    end

    def top_music(key)
      hot_trends[key]
    end
  end
end

Dễ thấy ở trên là một Plain Old class ruby rất đơn giản, có 2 functions

  • #hot_trends - là 1 hash dùng để store các config var
  • #top_music - function truy xuất config var theo key name, nếu trùng thì return value , ngược lại return nil

Cách truy xuất rất đơn giản:

MusicGuu::Configuration.new.top_music(:top_hit)
# => "See you again"

Đến đây chúng ta đã thỏa mãn yêu cầu truy xuất và có thể dừng lại tại đây. Tuy nhiên chúng ta vẫn có thể improve đoạn code trên. Vì việc tạo một object cho mỗi lần truy xuất rất ảnh hưởng tới tài nguyên mà các object config được tạo ra không cần thiết. Có thể kiểm chứng điều đó như sau:

MusicGuu::Configuration.new.top_music(:top_hit).object_id
# => 80144345091440

MusicGuu::Configuration.new.top_music(:top_hit).object_id
# => 80145304142669

Dễ thấy id của 2 instance khác nhau, => instance mới đã được tạo.

Do đó chúng ta refactor một chút đoạn code trên để chỉ tạo ta 1 object khi truy xuất thôi:

module MusicGuu
  class Configuration
    def self.instance
      @instance ||= self.new
    end

    # code cũ ở đây

Và thông qua instance:

MusicGuu::Configuration.instance.top_music(:top_hit)
# => "See you again"

Giờ check lại các instance được tạo ra nhé:

MusicGuu::Configuration.instance.top_music(:top_hit).object_id
# => 81132336967820

MusicGuu::Configuration.instance.top_music(:top_hit).object_id
# => 81132336967820

Dễ thấy id trùng khớp nên chỉ có 1 instance được tạo. 😃

Ngoài ra, chúng ta có thể sử dụng mixin Singleton để refactor như sau:

require 'singleton'

module MusicGuu
  class Configuration
    include Singleton

    def hot_trends
      @top ||= {
        top_hit: "See you again"
      }
    end

    def top_music(key)
      hot_trends[key]
    end
  end
end

Done, nó cung cấp interface API và thực hiện chức năng tương tự hàm .instance khi nãy.

Mình hy vọng với tip nhỏ này có thể giúp mọi người viết code Ruby sáng hơn. 😃 Mình cũng sẽ cố gắng tìm hiểu các tips khác về Ruby để chia sẻ với mọi người. Ai đi qua cho mình một + nhé. 😉


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí