Viime vuosina JavaScriptin yhden sivun sovelluskehysten ja mobiilisovellusten määrä on kasvanut huomattavasti. Tämä asettaa vastaavasti lisääntyneen kysynnän palvelinpuolen sovellusliittymille. Koska Ruby on Rails on yksi nykypäivän suosituimmista verkkokehityskehyksistä, se on luonnollinen valinta monien kehittäjien keskuudessa back-end -sovellusten luomiseen.
Silti vaikka Ruby on Rails -arkkitehtuurinen paradigma tekee back-end-sovellusliittymäsovellusten luomisen melko helpoksi Railsin avulla vain API: lle on ylivoimainen. Itse asiassa se on ylivoimaista siihen pisteeseen asti, että jopa Rails-tiimi on tunnistanut tämän ja siksi ottanut käyttöön uuden vain API-tilan versiossa 5. Tämän Ruby on Rails -sovelluksen uuden ominaisuuden avulla vain API-sovellusten luominen Railsille on entistä helpompaa ja kannattavampi vaihtoehto.
Mutta on myös muita vaihtoehtoja. Merkittävimmät ovat kaksi erittäin kypsää ja tehokasta helmiä, jotka yhdessä tarjoavat tehokkaita työkaluja palvelinpuolen sovellusliittymien luomiseen. He ovat Sinatra ja Jatko .
Molemmilla helmillä on erittäin runsas ominaisuusjoukko: Sinatra toimii verkkotunnuskohtaisena kielenä (DSL) verkkosovelluksille ja jatko toimii objektisuhdekartoituskerroksena (ORM). Joten katsotaanpa lyhyesti niitä kaikkia.
Sinatra on Rack-pohjainen verkkosovelluskehys. Rack on tunnettu Ruby-verkkopalvelimen käyttöliittymä. Sitä käyttävät monet kehykset, kuten esimerkiksi Ruby on Rails, ja se tukee monia verkkopalvelimia, kuten WEBrick, Thin tai Puma. Sinatra tarjoaa minimaalisen käyttöliittymän verkkosovellusten kirjoittamiseen Ruby-muodossa, ja yksi sen pakottavimmista ominaisuuksista on tuki väliohjelmistokomponenteille. Nämä komponentit ovat sovelluksen ja verkkopalvelimen välissä, ja ne voivat seurata ja käsitellä pyyntöjä ja vastauksia.
Tämän Rack-ominaisuuden käyttämiseksi Sinatra määrittelee sisäisen DSL: n verkkosovellusten luomiseen. Sen filosofia on hyvin yksinkertainen: Reitit esitetään HTTP-menetelmillä, joita seuraa reitti, joka sopii malliin. Rubiinilohko, jossa pyyntö käsitellään ja vastaus muodostetaan.
get '/' do 'Hello from sinatra' end
Reitin sovitusmalli voi sisältää myös nimetyn parametrin. Kun reittilohko suoritetaan, parametriarvo välitetään lohkolle params
: n kautta muuttuja.
get '/players/:sport_id' do # Parameter value accessible through params[:sport_id] end
Vastaavat mallit voivat käyttää välioperaattoria *
mikä asettaa parametriarvot saataville params[:splat]
-palvelun kautta.
get '/players/*/:year' do # /players/performances/2016 # Parameters - params['splat'] -> ['performances'], params[:year] -> 2016 end
Tämä ei ole loppu Sinatran reitin sovittamiseen liittyvistä mahdollisuuksista. Se voi käyttää monimutkaisempaa vastaavuuslogiikkaa säännöllisten lausekkeiden kautta sekä mukautettuja vastaavuuksia.
Sinatra ymmärtää kaikki vakio-HTTP-verbit, joita tarvitaan REST-sovellusliittymän luomiseen: Get, Post, Put, Patch, Delete ja Options. Reitin prioriteetit määräytyvät niiden määrittelyjärjestyksessä, ja ensimmäinen pyyntöä vastaava reitti palvelee pyyntöä.
Sinatran hakemukset voidaan kirjoittaa kahdella tavalla; käyttäen klassista tai modulaarista tyyliä. Suurin ero niiden välillä on se, että klassisella tyylillä meillä voi olla vain yksi Sinatra-sovellus Ruby-prosessia kohden. Muut erot ovat riittävän pieniä, jotta useimmissa tapauksissa ne voidaan jättää huomiotta ja käyttää oletusasetuksia.
Klassisen sovelluksen toteuttaminen on yksinkertaista. Meidän on vain ladattava Sinatra ja toteutettava reitin käsittelijät:
require 'sinatra' get '/' do 'Hello from Sinatra' end
Tallentamalla tämä koodi kohtaan demo_api_classic.rb
tiedosto, voimme käynnistää sovelluksen suoraan suorittamalla seuraavan komennon:
ruby demo_api_classic.rb
Jos sovellus on kuitenkin tarkoitus asentaa Rack-käsittelijöiden, kuten Passenger, kanssa, on parempi aloittaa se Rack-kokoonpanolla config.ru
tiedosto.
require './demo_api_classic' run Sinatra::Application
config.ru
-Painikkeella tiedosto paikallaan, sovellus käynnistetään seuraavalla komennolla:
rackup config.ru
Modulaariset Sinatra-sovellukset luodaan joko Sinatra::Base
tai Sinatra::Application
:
require 'sinatra' class DemoApi Kuinka jatko ja Sinatra ratkaisevat Rubyn API-ongelman
Viime vuosina JavaScriptin yhden sivun sovelluskehysten ja mobiilisovellusten määrä on kasvanut huomattavasti. Tämä asettaa vastaavasti lisääntyneen kysynnän palvelinpuolen sovellusliittymille. Koska Ruby on Rails on yksi nykypäivän suosituimmista verkkokehityskehyksistä, se on luonnollinen valinta monien kehittäjien keskuudessa back-end -sovellusten luomiseen.
Silti vaikka Ruby on Rails -arkkitehtuurinen paradigma tekee back-end-sovellusliittymäsovellusten luomisen melko helpoksi Railsin avulla vain API: lle on ylivoimainen. Itse asiassa se on ylivoimaista siihen pisteeseen asti, että jopa Rails-tiimi on tunnistanut tämän ja siksi ottanut käyttöön uuden vain API-tilan versiossa 5. Tämän Ruby on Rails -sovelluksen uuden ominaisuuden avulla vain API-sovellusten luominen Railsille on entistä helpompaa ja kannattavampi vaihtoehto.
Mutta on myös muita vaihtoehtoja. Merkittävimmät ovat kaksi erittäin kypsää ja tehokasta helmiä, jotka yhdessä tarjoavat tehokkaita työkaluja palvelinpuolen sovellusliittymien luomiseen. He ovat Sinatra ja Jatko .
Molemmilla helmillä on erittäin runsas ominaisuusjoukko: Sinatra toimii verkkotunnuskohtaisena kielenä (DSL) verkkosovelluksille ja jatko toimii objektisuhdekartoituskerroksena (ORM). Joten katsotaanpa lyhyesti niitä kaikkia.
Sinatra on Rack-pohjainen verkkosovelluskehys. Rack on tunnettu Ruby-verkkopalvelimen käyttöliittymä. Sitä käyttävät monet kehykset, kuten esimerkiksi Ruby on Rails, ja se tukee monia verkkopalvelimia, kuten WEBrick, Thin tai Puma. Sinatra tarjoaa minimaalisen käyttöliittymän verkkosovellusten kirjoittamiseen Ruby-muodossa, ja yksi sen pakottavimmista ominaisuuksista on tuki väliohjelmistokomponenteille. Nämä komponentit ovat sovelluksen ja verkkopalvelimen välissä, ja ne voivat seurata ja käsitellä pyyntöjä ja vastauksia.
Tämän Rack-ominaisuuden käyttämiseksi Sinatra määrittelee sisäisen DSL: n verkkosovellusten luomiseen. Sen filosofia on hyvin yksinkertainen: Reitit esitetään HTTP-menetelmillä, joita seuraa reitti, joka sopii malliin. Rubiinilohko, jossa pyyntö käsitellään ja vastaus muodostetaan.
get '/' do 'Hello from sinatra' end
Reitin sovitusmalli voi sisältää myös nimetyn parametrin. Kun reittilohko suoritetaan, parametriarvo välitetään lohkolle params
: n kautta muuttuja.
get '/players/:sport_id' do # Parameter value accessible through params[:sport_id] end
Vastaavat mallit voivat käyttää välioperaattoria *
mikä asettaa parametriarvot saataville params[:splat]
-palvelun kautta.
get '/players/*/:year' do # /players/performances/2016 # Parameters - params['splat'] -> ['performances'], params[:year] -> 2016 end
Tämä ei ole loppu Sinatran reitin sovittamiseen liittyvistä mahdollisuuksista. Se voi käyttää monimutkaisempaa vastaavuuslogiikkaa säännöllisten lausekkeiden kautta sekä mukautettuja vastaavuuksia.
Sinatra ymmärtää kaikki vakio-HTTP-verbit, joita tarvitaan REST-sovellusliittymän luomiseen: Get, Post, Put, Patch, Delete ja Options. Reitin prioriteetit määräytyvät niiden määrittelyjärjestyksessä, ja ensimmäinen pyyntöä vastaava reitti palvelee pyyntöä.
Sinatran hakemukset voidaan kirjoittaa kahdella tavalla; käyttäen klassista tai modulaarista tyyliä. Suurin ero niiden välillä on se, että klassisella tyylillä meillä voi olla vain yksi Sinatra-sovellus Ruby-prosessia kohden. Muut erot ovat riittävän pieniä, jotta useimmissa tapauksissa ne voidaan jättää huomiotta ja käyttää oletusasetuksia.
Klassisen sovelluksen toteuttaminen on yksinkertaista. Meidän on vain ladattava Sinatra ja toteutettava reitin käsittelijät:
require 'sinatra' get '/' do 'Hello from Sinatra' end
Tallentamalla tämä koodi kohtaan demo_api_classic.rb
tiedosto, voimme käynnistää sovelluksen suoraan suorittamalla seuraavan komennon:
ruby demo_api_classic.rb
Jos sovellus on kuitenkin tarkoitus asentaa Rack-käsittelijöiden, kuten Passenger, kanssa, on parempi aloittaa se Rack-kokoonpanolla config.ru
tiedosto.
require './demo_api_classic' run Sinatra::Application
config.ru
-Painikkeella tiedosto paikallaan, sovellus käynnistetään seuraavalla komennolla:
rackup config.ru
Modulaariset Sinatra-sovellukset luodaan joko Sinatra::Base
tai Sinatra::Application
:
require 'sinatra' class DemoApi 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.
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 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.