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

Phần giới thiệu công cụ về GraphQL với Ruby

Bạn có thể đã nghe các nhà phát triển ca ngợi những điều kỳ diệu của GraphQL. Trong loạt bài này, chúng tôi muốn tìm hiểu các công nghệ bằng cách sử dụng chúng và bài viết này sẽ giới thiệu cho các bạn một ứng dụng mẫu sử dụng GraphQL.

GraphQL là gì

GraphQL là một ngôn ngữ truy vấn và thời gian chạy có thể được sử dụng để xây dựng các API. Nó giữ một vị trí tương tự trong ngăn xếp phát triển như một API REST nhưng linh hoạt hơn. Không giống như REST, GraphQL cho phép máy khách chỉ định các định dạng và nội dung phản hồi. Cũng giống như SQL SELECT câu lệnh cho phép xác định kết quả truy vấn, GraphQL cho phép chỉ định cấu trúc dữ liệu JSON trả về. Theo phép tương tự SQL, GraphQL không cung cấp WHERE nhưng xác định các trường trên các đối tượng ứng dụng sẽ cung cấp dữ liệu cho phản hồi.

GraphQL, như tên cho thấy, mô hình hóa các API như thể ứng dụng là một biểu đồ dữ liệu. Mặc dù mô tả này có thể không phải là cách bạn xem ứng dụng của mình, nhưng nó là một mô hình được sử dụng trong hầu hết các hệ thống. Dữ liệu có thể được biểu diễn bởi JSON là một biểu đồ vì JSON chỉ là một biểu đồ có hướng. Nghĩ về ứng dụng như trình bày một mô hình đồ thị thông qua API sẽ làm cho GraphQL dễ hiểu hơn nhiều.

Sử dụng GraphQL trong một ứng dụng

Bây giờ chúng ta đã mô tả GraphQL trong phần tóm tắt, chúng ta hãy bắt đầu thực sự xây dựng một ứng dụng sử dụng GraphQL bằng cách bắt đầu với định nghĩa về mô hình dữ liệu hoặc biểu đồ. Năm ngoái, tôi có một thú vui mới. Tôi đang học cách chơi âm bass thẳng đứng cũng như tìm hiểu về âm nhạc nói chung, vì vậy tôi nghĩ đến một ví dụ liên quan đến âm nhạc khi tạo ra một ứng dụng demo.

Các loại đối tượng trong ví dụ là Nghệ sĩ Bài hát . Nghệ sĩ có nhiều Bài hát và một Bài hát được liên kết với Nghệ sĩ . Mỗi loại đối tượng có các thuộc tính như name .

Xác định API

GraphQL sử dụng SDL (Ngôn ngữ định nghĩa lược đồ) đôi khi được gọi là "ngôn ngữ định nghĩa hệ thống kiểu" trong đặc tả GraphQL. Về lý thuyết, các loại GraphQL có thể được định nghĩa bằng bất kỳ ngôn ngữ nào nhưng ngôn ngữ bất khả tri phổ biến nhất là SDL, vì vậy hãy sử dụng SDL để định nghĩa API.

type Artist {
  name: String!
  songs: [Song]
  origin: [String]
}

type Song {
  name: String!
  artist: Artist
  duration: Int
  release: String
}

Một Nghệ sĩ name đó là String . Dấu chấm than có nghĩa là trường non-null . songs là một mảng của Bài hát đối tượng và origin là một String mảng. Bài hát tương tự nhưng với một trường lẻ. release trường phải là loại thời gian hoặc ngày nhưng GraphQL không có loại đó được xác định là loại cốt lõi. Để có tính di động hoàn chỉnh giữa các triển khai GraphQL khác nhau, một String Được sử dụng. Việc triển khai GraphQL mà chúng tôi sẽ sử dụng có Time đã thêm nhập, vì vậy hãy thay đổi Bài hát định nghĩa để release trường là Time loại hình. Giá trị trả về sẽ là String , nhưng bằng cách đặt loại thành Time chúng tôi ghi lại API chính xác hơn.

  release: Time

Bước cuối cùng là mô tả cách lấy một hoặc nhiều đối tượng. Điều này được gọi là gốc hoặc, đối với các truy vấn, là gốc truy vấn. Thư mục gốc của chúng tôi sẽ chỉ có một trường hoặc một phương thức được gọi là artist và sẽ yêu cầu một name nghệ sĩ .

type Query {
  artist(name: String!): Artist
}

Viết đơn

Hãy xem cách chúng ta sẽ sử dụng điều này trong một ứng dụng. Có một số cách triển khai máy chủ GraphQL cho Ruby. Một số cách tiếp cận yêu cầu SDL ở trên phải được dịch sang một ngôn ngữ tương đương Ruby. Agoo, một máy chủ HTTP mà tôi đã xây dựng, sử dụng định nghĩa SDL như nó vốn có và mã Ruby là Ruby vani đơn giản, vì vậy đó là những gì chúng tôi sẽ sử dụng.

Lưu ý rằng các lớp Ruby phù hợp với các kiểu GraphQL. Bằng cách đặt tên lớp Ruby khớp với tên loại GraphQL, chúng tôi không thêm bất kỳ sự phức tạp nào không cần thiết.

class Artist
  attr_reader :name
  attr_reader :songs
  attr_reader :origin
 
  def initialize(name, origin)
    @name = name
    @songs = []
    @origin = origin
  end
 
  # Only used by the Song to add itself to the artist.
  def add_song(song)
    @songs << song
  end
end
 
class Song
  attr_reader :name     # string
  attr_reader :artist   # reference
  attr_reader :duration # integer
  attr_reader :release  # time
 
  def initialize(name, artist, duration, release)
    @name = name
    @artist = artist
    @duration = duration
    @release = release
    artist.add_song(self)
  end
end

Các phương thức khớp với các trường trong các lớp Ruby. Lưu ý rằng các phương thức không có đối số hoặc args={} . Đây là những gì API GraphQL mong đợi và việc triển khai của chúng tôi ở đây cũng phù hợp. initialize được sử dụng để thiết lập dữ liệu cho ví dụ, như chúng ta sẽ thấy ngay sau đây.

Lớp gốc truy vấn cũng cần được xác định. Lưu ý artist phương thức phù hợp với SDL Query loại gốc. attr_reader cho các nghệ sĩ artists cũng đã được thêm vào. Điều đó sẽ được hiển thị với API chỉ bằng cách thêm trường đó vào Query nhập vào tài liệu SDL.

class Query
  attr_reader :artists
 
  def initialize(artists)
    @artists = artists
  end
 
  def artist(args={})
    @artists[args['name']]
  end
end

Gốc GraphQL (không nên nhầm lẫn với gốc truy vấn) nằm phía trên gốc truy vấn. GraphQL định nghĩa nó có ba trường tùy chọn. Trong trường hợp này, lớp Ruby thực hiện trên query đồng ruộng. Trình khởi tạo tải lên một số dữ liệu cho một ban nhạc Indie từ New Zealand mà tôi muốn nghe.

class Schema
  attr_reader :query
  attr_reader :mutation
  attr_reader :subscription
 
  def initialize()
    # Set up some data for testing.
    artist = Artist.new('Fazerdaze', ['Morningside', 'Auckland', 'New Zealand'])
    Song.new('Jennifer', artist, 240, Time.utc(2017, 5, 5))
    Song.new('Lucky Girl', artist, 170, Time.utc(2017, 5, 5))
    Song.new('Friends', artist, 194, Time.utc(2017, 5, 5))
    Song.new('Reel', artist, 193, Time.utc(2015, 11, 2))
    @artists = {artist.name => artist}
 
    @query = Query.new(@artists)
  end
end

Thiết lập cuối cùng là thực hiện cụ thể. Tại đây, máy chủ được khởi tạo để bao gồm một trình xử lý cho /graphql Đường dẫn yêu cầu HTTP và sau đó nó được bắt đầu.

Agoo::Server.init(6464, 'root', thread_count: 1, graphql: '/graphql')
Agoo::Server.start()

Sau đó, việc triển khai GraphQL được định cấu hình với SDL được xác định trước đó ($songs_sdl ) và sau đó ứng dụng sẽ ngủ trong khi máy chủ xử lý các yêu cầu.

Agoo::GraphQL.schema(Schema.new) {
  Agoo::GraphQL.load($songs_sdl)
}
sleep

Mã cho ví dụ này có thể được tìm thấy trên GitHub.

Sử dụng API

Để kiểm tra API, bạn có thể sử dụng trình duyệt web, Postman hoặc curl .

Truy vấn GraphQL để thử có dạng như sau:

{
  artist(name:"Fazerdaze") {
    name
    songs{
      name
      duration
    }
  }
}

Truy vấn yêu cầu Nghệ sĩ được đặt tên là Fazerdaze và trả về namesongs trong tài liệu JSON. Đối với mỗi Bài hát tên artistsduration của Bài hát được trả về trong một đối tượng JSON. Đầu ra sẽ giống như thế này.

{
  "data": {
    "artist": {
      "name": "Fazerdaze",
      "songs": [
        {
          "name": "Jennifer",
          "duration": 240
        },
        {
          "name": "Lucky Girl",
          "duration": 170
        },
        {
          "name": "Friends",
          "duration": 194
        },
        {
          "name": "Reel",
          "duration": 193
        }
      ]
    }
  }
}

Sau khi loại bỏ khoảng trắng tùy chọn trong truy vấn, HTTP GET được tạo bằng curl sẽ trả về nội dung đó.

curl -w "\n" 'localhost:6464/graphql?query=\{artist(name:"Fazerdaze")\{name,songs\{name,duration\}\}\}&indent=2'

Hãy thử thay đổi truy vấn và thay thế duration với release và lưu ý việc chuyển đổi Ruby Time thành chuỗi JSON.

Chuyển sang bài hát

Chúng tôi rất thích chơi với GraphQL và chúng tôi hy vọng bạn đã gắn thẻ và học được điều gì đó trên đường đi. Cảm ơn bạn, bạn đã là một khán giả tuyệt vời. Nếu bạn muốn nói thêm về Ruby, chúng ta sẽ đến quầy bán hàng.