end

Lauseke, joka alkaa run! käytetään sovelluksen käynnistämiseen suoraan ruby demo_api.rb: lla, aivan kuten perinteisessä sovelluksessa. Toisaalta, jos sovellus on tarkoitus ottaa käyttöön Rackin kanssa, käsittelijöiden sisältö rackup.ru täytyy olla:

require './demo_api' run DemoApi

Jatko

Jatko on sarjan toinen työkalu. Toisin kuin ActiveRecord, joka on osa Ruby on Rails -sarjaa, Sequelin riippuvuudet ovat hyvin pieniä. Samalla se on varsin monipuolinen ja sitä voidaan käyttää kaikenlaisiin tietokannan manipulointitehtäviin. Yksinkertaisella verkkotunnuskohtaisella kielellään Sequel vapauttaa kehittäjän kaikista ongelmista, jotka liittyvät yhteyksien ylläpitoon, SQL-kyselyjen rakentamiseen, tietojen hakemiseen (ja tietojen lähettämiseen takaisin tietokantaan).

Esimerkiksi yhteyden luominen tietokantaan on hyvin yksinkertaista:

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

Connect-menetelmä palauttaa tietokantaobjektin, tässä tapauksessa Sequel::Postgres::Database, jota voidaan edelleen käyttää raakan SQL: n suorittamiseen.

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

Vaihtoehtoisesti voit luoda uuden datajoukko-objektin:

DB[:players]

Molemmat lauseet luovat tietojoukko-objektin, joka on jatko-peruskokonaisuus.

Yksi tärkeimmistä jatko-tietojoukon ominaisuuksista on, että se ei suorita kyselyitä välittömästi. Tämä antaa mahdollisuuden tallentaa aineistoja myöhempää käyttöä varten ja useimmissa tapauksissa ketjuttaa ne.

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

Joten, jos tietojoukko ei osu tietokantaan heti, on kysymys, milloin se tapahtuu? Jatko suorittaa SQL: n tietokannassa, kun käytetään ns. Suoritettavia menetelmiä. Nämä menetelmät ovat muutamia mainitakseni: all, each, map, first ja last.

Jatko on laajennettavissa, ja sen laajentaminen on seurausta perustavanlaatuisesta arkkitehtonisesta päätöksestä rakentaa pieni ydin, jota täydennetään laajennusjärjestelmällä. Ominaisuudet lisätään helposti laajennusten kautta, jotka ovat itse asiassa Ruby-moduuleja. Tärkein laajennus on Model kytkeä. Se on tyhjä laajennus, joka ei määritä itse luokka- tai instanssimenetelmiä. Sen sijaan se sisältää muita laajennuksia (alamoduuleja), jotka määrittelevät luokan, ilmentymän tai mallin tietojoukkomenetelmät. Malli-laajennus mahdollistaa jatko-osan käytön objektin relaatiokartoitus (ORM) -työkaluna, ja sitä kutsutaan usein 'peruslaajennukseksi'.

class Player

Jatkomalli jäsentää tietokantamallin automaattisesti ja määrittää kaikki tarvittavat käyttöoikeusmenetelmät kaikille sarakkeille. Se olettaa, että taulukon nimi on monikko ja on alleviivattu malli mallinimestä. Jos on tarvetta työskennellä tietokantojen kanssa, jotka eivät noudata tätä nimeämiskäytäntöä, taulukon nimi voidaan nimenomaisesti asettaa, kun malli on määritelty.

class Player

Joten meillä on nyt kaikki mitä tarvitsemme back-end-sovellusliittymän rakentamisen aloittamiseksi.

API: n rakentaminen

Koodirakenne

Toisin kuin Rails, Sinatra ei aseta mitään projektirakennetta. Koska koodin järjestäminen on kuitenkin aina helppoa ylläpidon ja kehittämisen helpottamiseksi, teemme sen myös täällä seuraavalla hakemistorakenteella:

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

Sovelluksen kokoonpano ladataan nykyisen ympäristön YAML-määritystiedostosta seuraavilla tavoilla:

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

Oletuksena Sinatra::Applicationsettings.environment arvo on development, ja sitä muutetaan asettamalla RACK_ENV ympäristömuuttuja.

Lisäksi sovelluksemme on ladattava kaikki tiedostot kolmesta muusta hakemistosta. Voimme tehdä sen helposti juoksemalla:

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

Ensi silmäyksellä tämä lataustapa saattaa näyttää hyvältä. Tällä koodirivillä emme kuitenkaan voi helposti ohittaa tiedostoja, koska se lataa kaikki tiedostot taulukon hakemistoista. Siksi käytämme tehokkaampaa yhden tiedoston latausmenetelmää, joka olettaa, että jokaisessa kansiossa on luettelotiedosto init.rb, joka lataa kaikki muut tiedostot hakemistosta. Lisäksi lisäämme kohdehakemiston Ruby-latauspolulle:

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

Tämä lähestymistapa vaatii hieman enemmän työtä, koska jokaisessa init.rb täytyy pitää yllä vaatimuslausekkeita tiedosto, mutta vastineeksi saamme enemmän hallintaa ja voimme helposti jättää yhden tai useamman tiedoston pois poistamalla ne luettelosta init.rb tiedosto kohdehakemistossa.

API-todennus

Ensimmäinen asia, jota tarvitsemme jokaisessa sovellusliittymässä, on todennus. Toteutamme sen auttajamoduulina. Täydellinen todennuslogiikka on helpers/authentication.rb tiedosto.

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

Nyt meidän on vain ladattava tämä tiedosto lisäämällä vaatimuslauseke auttaja-luettelotiedostoon (helpers/init.rb) ja kutsuttava authenticate! menetelmä Sinatran before koukku, joka suoritetaan ennen minkä tahansa pyynnön käsittelyä.

before do authenticate! end

Tietokanta

Seuraavaksi meidän on valmisteltava tietokanta sovellusta varten. Tietokannan valmisteluun on monia tapoja, mutta koska käytämme Sequeliä, on luonnollista tehdä se käyttämällä siirtimiä. Jatkossa on kaksi siirtotyyppiä - kokonaisluku ja aikaleima. Jokaisella on etunsa ja haittansa. Esimerkissämme päätimme käyttää jatkoajan aikaleimansiirtäjää, joka vaatii siirtotiedostojen etuliitteen aikaleimalla. Aikaleimansiirtäjä on erittäin joustava ja voi hyväksyä erilaisia ​​aikaleimamuotoja, mutta käytämme vain sellaista, joka koostuu vuodesta, kuukaudesta, päivästä, tunnista, minuutista ja sekunnista. Tässä on kaksi siirtotiedostoa:

# 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

Olemme nyt valmiita luomaan tietokannan, jossa on kaikki taulukot.

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

Lopuksi meillä on mallitiedostot sport.rb ja player.rb models hakemistoon.

# models/sport.rb class Sport

Tässä käytämme jatkoa tapaa määritellä mallisuhteet, joissa Sport objectilla on monia pelaajia ja Player voi olla vain yksi urheilulaji. Kukin malli määrittelee myös sen to_api method, joka palauttaa hash -sarjan, joka on sarjoitettava. Tämä on yleinen lähestymistapa, jota voimme käyttää eri muodoissa. Jos kuitenkin käytämme API: ssa vain JSON-muotoa, voisimme käyttää Rubyn to_json -muotoa kanssa only argumentti rajoittaa sarjallisuus vaadittuihin määritteisiin, ts. player.to_json(only: [:id, :name, :sport_i]) Tietenkin voisimme määritellä myös BaseModel joka perii Sequel::Model ja määrittää oletusarvon to_api menetelmä, josta kaikki mallit voivat periä.

Nyt voimme aloittaa todellisten API-päätepisteiden toteuttamisen.

API-päätepisteet

Säilytämme kaikkien päätepisteiden määritelmän tiedostoissa routes hakemistoon. Koska käytämme luettelotiedostoja tiedostojen lataamiseen, ryhmittelemme reitit resurssien mukaan (ts. Pidämme kaikki urheiluun liittyvät reitit sports.rb -tiedostossa, kaikki pelaajien reitit routes.rb ja niin edelleen).

# routes/sports.rb class DemoApi

Sisäkkäiset reitit, kuten kaikkien pelaajien saaminen yhteen urheilulajiin /sports/:id/players, voidaan määrittää joko sijoittamalla ne muiden reittien kanssa tai luomalla erillinen resurssitiedosto, joka sisältää vain sisäkkäiset reitit.

Määritetyillä reiteillä sovellus on nyt valmis vastaanottamaan pyynnöt:

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

Huomaa, että helpers/authentication.rb -kohdassa määritetyn sovelluksen todennusjärjestelmän edellyttämällä tavalla tiedosto, välitämme tunnistetiedot suoraan pyyntöparametreihin.

Liittyvät: Grape Gem -opetusohjelma: Kuinka rakentaa REST-tyyppinen sovellusliittymä Rubiin

Johtopäätös

Tässä yksinkertaisessa esimerkkisovelluksessa esitetyt periaatteet koskevat kaikkia API-sovelluksia. Se ei perustu MVC (model-view-controller) -arkkitehtuuriin, mutta siinä erotetaan selkeästi vastuualueet samalla tavalla; täydellinen liiketoimintalogiikka säilytetään mallitiedostoissa, kun taas pyyntöjen käsittely tapahtuu Sinatran reittimenetelmissä. Päinvastoin kuin MVC-arkkitehtuurissa, jossa näkymiä käytetään vastausten esittämiseen, tämä sovellus tekee sen samassa paikassa, jossa se käsittelee pyyntöjä - reittimenetelmissä. Uusilla auttajatiedostoilla sovellusta voidaan helposti laajentaa lähettämään sivunumeroita tai tarvittaessa pyytää rajoituksia takaisin käyttäjälle vastausotsikoissa.

Loppujen lopuksi olemme rakentaneet täydellisen sovellusliittymän, jossa on hyvin yksinkertainen työkalupakki ja menettämättä mitään toimintoja. Rajoitettu määrä riippuvuuksia auttaa varmistamaan, että sovellus latautuu ja käynnistyy paljon nopeammin ja että sen muistinjälki on paljon pienempi kuin Rails-pohjaisella. Joten seuraavan kerran aloitat uuden sovellusliittymän valmistamisen vuonna Rubiini , harkitse Sinatran ja Sequelin käyttöä, koska ne ovat erittäin tehokkaita työkaluja tällaiseen käyttötapaukseen.