end

run!で始まるステートメント従来のアプリケーションと同様に、ruby demo_api.rbを使用してアプリケーションを直接起動するために使用されます。一方、アプリケーションをRackでデプロイする場合、ハンドラーの内容はrackup.ruです。でなければなりません:

require './demo_api' run DemoApi

続編

続編は、このセットの2番目のツールです。 Ruby on Railsの一部であるActiveRecordとは対照的に、Sequelの依存関係は非常に小さいです。同時に、それは非常に豊富な機能であり、あらゆる種類のデータベース操作タスクに使用できます。 Sequelは、その単純なドメイン固有言語により、接続の維持、SQLクエリの構築、データベースからのデータのフェッチ(およびデータベースへのデータの送信)に関するすべての問題から開発者を解放します。

たとえば、データベースとの接続を確立するのは非常に簡単です。

DB = Sequel.connect(adapter: :postgres, database: 'my_db', host: 'localhost', user: 'db_user')

connectメソッドはデータベースオブジェクト(この場合はSequel::Postgres::Database)を返します。これは、生のSQLを実行するためにさらに使用できます。

DB['select count(*) from players']

または、新しいデータセットオブジェクトを作成するには:

DB[:players]

これらのステートメントは両方とも、基本的なSequelエンティティであるデータセットオブジェクトを作成します。

Sequelデータセットの最も重要な機能の1つは、クエリをすぐに実行しないことです。これにより、後で使用するためにデータセットを保存し、ほとんどの場合、それらをチェーンすることができます。

users = DB[:players].where(sport: 'tennis')

したがって、データセットがデータベースにすぐにヒットしない場合、問題はいつですか? Sequelは、いわゆる「実行可能メソッド」が使用されると、データベースでSQLを実行します。これらのメソッドは、いくつか例を挙げると、alleachmapfirst、およびlastです。

続編は拡張可能であり、その拡張性は、プラグインシステムで補完された小さなコアを構築するという基本的なアーキテクチャ上の決定の結果です。機能は、実際にはRubyモジュールであるプラグインを介して簡単に追加できます。最も重要なプラグインはModelです。プラグイン。これは、クラスまたはインスタンスメソッドを単独で定義しない空のプラグインです。代わりに、クラス、インスタンス、またはモデルのデータセットメソッドを定義する他のプラグイン(サブモジュール)が含まれています。モデルプラグインを使用すると、Sequelをオブジェクトリレーショナルマッピング(ORM)ツールとして使用でき、「ベースプラグイン」と呼ばれることもあります。

javascriptでAPIを作成する方法
class Player

Sequelモデルは、データベーススキーマを自動的に解析し、すべての列に必要なすべてのアクセサーメソッドを設定します。テーブル名は複数形であり、モデル名の下線付きバージョンであると想定しています。この命名規則に従わないデータベースを操作する必要がある場合は、モデルの定義時にテーブル名を明示的に設定できます。

class Player

これで、バックエンドAPIの構築を開始するために必要なものがすべて揃いました。

APIの構築

コード構造

Railsとは異なり、Sinatraはプロジェクト構造を強制しません。ただし、メンテナンスと開発を容易にするためにコードを整理することは常に良い習慣であるため、ここでも次のディレクトリ構造を使用して行います。

project root |-config |-helpers |-models |-routes

アプリケーション構成は、現在の環境のYAML構成ファイルから次のようにロードされます。

Sinatra::Application.config_file File.join(File.dirname(__FILE__), 'config', '#{Sinatra::Application.settings.environment}_config.yml')

デフォルトでは、Sinatra::Applicationsettings.environment値はdevelopment,ですRACK_ENVを設定することで変更されます環境変数。

さらに、アプリケーションは他の3つのディレクトリからすべてのファイルをロードする必要があります。これは、次のコマンドを実行することで簡単に実行できます。

%w{helpers models routes}.each {|dir| Dir.glob('#{dir}/*.rb', &method(:require))}

一見すると、このロード方法は便利に見えるかもしれません。ただし、この1行のコードでは、配列内のディレクトリからすべてのファイルが読み込まれるため、ファイルを簡単にスキップすることはできません。そのため、より効率的な単一ファイルの読み込みアプローチを使用します。このアプローチでは、各フォルダーにマニフェストファイルinit.rbがあり、ディレクトリから他のすべてのファイルを読み込みます。また、Rubyのロードパスにターゲットディレクトリを追加します。

%w{helpers models routes}.each do |dir| $LOAD_PATH << File.expand_path('.', File.join(File.dirname(__FILE__), dir)) require File.join(dir, 'init') end

init.rbでrequireステートメントを維持する必要があるため、このアプローチにはもう少し作業が必要です。ファイルですが、その見返りとして、より詳細な制御が可能になり、マニフェストからファイルを削除することで、1つ以上のファイルを簡単に除外できますinit.rbターゲットディレクトリ内のファイル。

2017年のcvvと郵便番号でハッキングされたクレジットカード番号

API認証

各APIで最初に必要なのは認証です。ヘルパーモジュールとして実装します。完全な認証ロジックはhelpers/authentication.rbにありますファイル。

require 'multi_json' module Sinatra module Authentication def authenticate! client_id = request['client_id'] client_secret = request['client_secret'] # Authenticate client here halt 401, MultiJson.dump({message: 'You are not authorized to access this resource'}) unless authenticated? end def current_client @current_client end def authenticated? !current_client.nil? end end helpers Authentication end

ここで行う必要があるのは、ヘルパーマニフェストファイル(helpers/init.rb)にrequireステートメントを追加してこのファイルをロードし、authenticate!を呼び出すことだけです。シナトラのメソッドbeforeリクエストを処理する前に実行されるフック。

before do authenticate! end

データベース

次に、アプリケーション用にデータベースを準備する必要があります。データベースを準備する方法はたくさんありますが、私たちはSequelを使用しているので、移行者を使用して準備するのが自然です。 Sequelには、整数ベースとタイムスタンプベースの2つの移行タイプがあります。それぞれに長所と短所があります。この例では、Sequelのタイムスタンプ移行ツールを使用することにしました。これには、移行ファイルの前にタイムスタンプを付ける必要があります。タイムスタンプ移行機能は非常に柔軟性があり、さまざまなタイムスタンプ形式を受け入れることができますが、年、月、日、時、分、秒で構成されるもののみを使用します。 2つの移行ファイルは次のとおりです。

# db/migrations/20160710094000_sports.rb Sequel.migration do change do create_table(:sports) do primary_key :id String :name, :null => false end end end # db/migrations/20160710094100_players.rb Sequel.migration do change do create_table(:players) do primary_key :id String :name, :null => false foreign_key :sport_id, :sports end end end

これで、すべてのテーブルを含むデータベースを作成する準備が整いました。

bundle exec sequel -m db/migrations sqlite://db/development.sqlite3

最後に、モデルファイルがありますsport.rbおよびplayer.rb modelsでディレクトリ。

# models/sport.rb class Sport

ここでは、モデルの関係を定義する続編の方法を採用しています。ここで、Sportオブジェクトには多くのプレーヤーがいて、Playerスポーツは1つだけです。また、各モデルはそのto_apiを定義しますメソッド。シリアル化する必要のある属性を持つハッシュを返します。これは、さまざまな形式に使用できる一般的なアプローチです。ただし、APIでJSON形式のみを使用する場合は、Rubyのto_jsonを使用できます。 onlyでシリアル化を必要な属性、つまりplayer.to_json(only: [:id, :name, :sport_i])に制限する引数。もちろん、BaseModelを定義することもできます。 Sequel::Modelから継承しますデフォルトを定義しますto_apiメソッド。継承元からすべてのモデルを継承できます。

これで、実際のAPIエンドポイントの実装を開始できます。

APIエンドポイント

routes内のファイル内のすべてのエンドポイントの定義を保持しますディレクトリ。ファイルの読み込みにマニフェストファイルを使用しているため、ルートをリソースごとにグループ化します(つまり、すべてのスポーツ関連ルートをsports.rbファイルに保持し、すべてのプレーヤールートをroutes.rbに保持します)。

# routes/sports.rb class DemoApi

1つのスポーツ/sports/:id/players内のすべてのプレーヤーを取得するルートのように、ネストされたルートは、他のルートと一緒に配置するか、ネストされたルートのみを含む別のリソースファイルを作成することによって定義できます。

指定されたルートで、アプリケーションはリクエストを受け入れる準備ができました。

curl -i -XGET 'http://localhost:9292/sports?client_id=&client_secret='

helpers/authentication.rbで定義されているアプリケーションの認証システムで必要とされることに注意してくださいファイルの場合、リクエストパラメータで資格情報を直接渡します。

関連: Grape Gemチュートリアル:RubyでRESTのようなAPIを構築する方法

結論

この単純なサンプルアプリケーションで示されている原則は、すべてのAPIバックエンドアプリケーションに適用されます。これは、model-view-controller(MVC)アーキテクチャに基づいていませんが、同様の方法で責任の明確な分離を維持します。リクエストの処理がSinatraのroutesメソッドで行われている間、完全なビジネスロジックはモデルファイルに保持されます。ビューが応答をレンダリングするために使用されるMVCアーキテクチャとは対照的に、このアプリケーションは、要求を処理するのと同じ場所で、つまりroutesメソッドでそれを実行します。新しいヘルパーファイルを使用すると、アプリケーションを簡単に拡張して、ページ付けを送信したり、必要に応じて、応答ヘッダーで制限情報をユーザーに返すことができます。

最終的に、機能を失うことなく、非常にシンプルなツールセットを使用して完全なAPIを構築しました。依存関係の数が限られているため、アプリケーションのロードと起動がはるかに速くなり、Railsベースのものよりもメモリフットプリントがはるかに小さくなります。したがって、次回、で新しいAPIの作業を開始するとき ルビー 、SinatraとSequelは、このようなユースケースにとって非常に強力なツールであるため、使用を検討してください。