Computer >> Máy Tính >  >> Lập trình >> Ruby

3 cách để định cấu hình trình gói API Ruby của bạn

Khi bạn sử dụng Ruby để bọc một API, bạn phải có cách để cấu hình nó. Có thể trình bao bọc cần tên người dùng và khóa bí mật hoặc có thể chỉ là máy chủ lưu trữ.

Có một số cách khác nhau để xử lý điều này. Vậy bạn nên chọn cái nào?

Cách dễ dàng, toàn cầu

Bạn có thể muốn dịch vụ của mình hoạt động như mọi khi. Bất kể bạn đang ở đâu trong ứng dụng của mình, bạn luôn có ứng dụng sẵn sàng để sử dụng. Nếu không, bạn sẽ tốn ba dòng định cấu hình nó cho mỗi dòng sử dụng nó!

Bạn có thể đặt cấu hình toàn cục, sử dụng các hằng số hoặc thuộc tính lớp:

config / initializers / product_api.rb
ProductApi.root = "https://staging-host.example.com/"
ProductApi.user = "justin"
ProductApi.secret = "mysecret123"
app / controllers / products_controller.rb
def show
  @product = ProductApi.find(params[:id])
end

Rất nhiều đá quý sử dụng mẫu này. Nó khá dễ viết và thực sự dễ sử dụng. Nhưng nó có một số vấn đề lớn:

  • Bạn chỉ có thể có một ProductApi .

    Nếu bạn muốn sử dụng API sản phẩm với tư cách là hai người dùng khác nhau hoặc truy cập các máy chủ khác nhau từ một ứng dụng, thì bạn đã không gặp may.

  • ProductApi có dữ liệu toàn cầu dễ vô tình thay đổi.

    Nếu một chuỗi hoặc một phần ứng dụng của bạn đã thay đổi ProductApi.user , mọi thứ khác bằng cách sử dụng ProductApi sẽ phá vỡ. Và đó là những đau đớn lỗi cần theo dõi.

Vì vậy, các biến lớp có một số vấn đề. Điều gì sẽ xảy ra nếu bạn định cấu hình phiên bản của lớp API sản phẩm của bạn, thay vào đó?

Với #initialize ?

Nếu bạn đã sử dụng các phiên bản, bạn sẽ tạo và định cấu hình trình bao bọc API của mình khi cần:

app / controllers / products_controller.rb
def show
  product_api = ProductApi.new(
    root: "https://staging-host.example.com/",
    user: "justin",
    secret: "mysecret123")
  @product = product_api.find(params[:id])
end

Bây giờ, bạn có thể chuyển các chi tiết khác nhau đến API của mình bất cứ khi nào bạn sử dụng nó. Không có phương thức hoặc chuỗi nào khác đang sử dụng phiên bản của bạn, vì vậy bạn không phải lo lắng về việc nó thay đổi mà bạn không biết.

Điều này có vẻ tốt hơn. Nhưng mọi chuyện vẫn không dễ dàng như mong đợi. Vì bạn phải định cấu hình API của mình mọi lúc bạn sử dụng nó.

Hầu hết thời gian bạn không quan tâm API được thiết lập như thế nào, bạn chỉ muốn sử dụng nó với các tùy chọn lành mạnh. Nhưng khi bạn đang làm việc với các phiên bản, mọi phần của ứng dụng của bạn sử dụng API phải biết cách định cấu hình nó.

Nhưng có một cách để có được sự thuận tiện của truy cập toàn cầu, sử dụng các giá trị mặc định tốt, trong khi vẫn có thể thay đổi nó nếu bạn cần.

Và mẫu này xuất hiện mọi lúc ở một nơi thú vị:phát triển OS X và iOS.

Làm cách nào để bạn có được giá trị mặc định tốt tính linh hoạt?

Điều gì sẽ xảy ra nếu bạn có thể định cấu hình từng phiên bản của trình bao bọc API của mình, nhưng bạn cũng có một phiên bản "mặc định" chung khi bạn không quan tâm?

Bạn sẽ thấy mẫu “defaultSomething” hoặc “sharedW Anything” này trên SDK iOS và Mac OS:

[[NSURLSession sharedSession] downloadTaskWithURL:@"https://www.google.com"];

[[NSFileManager defaultManager] removeItemAtPath:...];

Và bạn vẫn có thể yêu cầu các phiên bản của các lớp này nếu bạn cần nhiều hơn những gì mặc định cung cấp cho bạn:

NSURLSession *session = [NSURLSession sessionWithConfiguration:...];

NSFileManager fileManager = [[NSFileManager alloc] init];

Bạn có thể tạo thứ gì đó tương tự trong Ruby, với default_api phương thức lớp:

app / controllers / products_controller.rb
def show
  @product = ProductApi.default_product_api.find(params[:id])
end

...

def show_special
  special_product_api = ProductApi.new(
    root: "https://special-product-host.example.com/"
    user: "justin"
    secret: "mysecret123")
  @special_product = special_product_api.find(params[:id])
end

Và việc triển khai có thể trông giống như sau:

class ProductApi
  def initialize(root:, user:, secret:)
    @root, @user, @secret = root, user, secret
  end

  def self.default_api
    @default_api ||= new(
      root: ENV['PRODUCT_API_ROOT'],
      user: ENV['PRODUCT_API_USER'],
      secret: ENV['PRODUCT_API_SECRET'])
  end

  def find(product_id)
    ...
  end
end

Ở đây, tôi đã sử dụng các biến môi trường trong default_api , nhưng bạn cũng có thể sử dụng các tệp cấu hình. Và bạn có thể chuyển đổi ||= để sử dụng chuỗi lưu trữ cục bộ hoặc yêu cầu thay thế.

Nhưng đây là một khởi đầu tốt.

Hầu hết các đá quý mà tôi đã thấy, như đá quý Twitter, sẽ yêu cầu bạn định cấu hình và tạo từng đối tượng API khi bạn cần chúng. Đây là một giải pháp OK (mặc dù tôi thường thấy mọi người gán những thứ này cho hình cầu dù sao ).

Nhưng nếu bạn tiến thêm một bước nữa và cũng sử dụng đối tượng mặc định được định cấu hình trước, bạn sẽ có thời gian thoải mái hơn nhiều.