Kuinka lisätä tehokas hakukone Rails-taustaohjelmaan

Kuva Simon Abrams on Unsplash

Kokemuksenani Ruby on Rails -kehittäjänä jouduin usein käsittelemään hakuominaisuuksien lisäämistä verkkosovelluksiin. Itse asiassa melkein kaikki sovellukset, joissa työskentelin jossain vaiheessa, tarvitsivat hakukoneominaisuuksia, kun taas monilla niistä oli hakukone tärkein ydintoiminto.

Monet päivittäin käyttämämme sovellukset olisivat hyödyttömiä ilman hyvää hakukonetta ytimessä. Esimerkiksi Amazonista voit löytää tietyn tuotteen sivustossa olevista yli 550 miljoonasta tuotteesta muutamassa sekunnissa - kaikki kiitos täydellisen tekstin haun yhdistettynä luokkasuodattimiin, puoliin ja suositusjärjestelmään.

Airbnb: llä voit etsiä asuntoa yhdistämällä geospatiaalisen haun suodattimilla talon ominaisuuksista, kuten mitat, hinta, käytettävissä olevat päivämäärät ja niin edelleen.

Ja Spotify, Netflix, Ebay, Youtube ... kaikki luottavat suuresti hakukoneeseen.

Tässä artikkelissa kuvaan kuinka kehittää Ruby on Rails 5 API -taustaohjelma Elasticsearchin kanssa. DB Engines Rankingin mukaan Elasticsearch on tällä hetkellä suosituin avoimen lähdekoodin hakualusta.

Tässä artikkelissa ei käsitellä Elasticsearchin yksityiskohtia ja kuinka sitä verrataan kilpailijoihin, kuten Sphinx ja Solr. Sen sijaan se on vaiheittainen opas JSON-sovellusohjelman toteuttamiseen Ruby on Rails -sovelluksella ja Elasticsearch-sovelluksella käyttämällä Test Driven Development -lähestymistapaa.

Tämä artikkeli kattaa:

  1. Elastisen haun asennus testi-, kehitys- ja tuotantoympäristöihin
  2. Ruby on Rails -ympäristön asetukset
  3. Mallien indeksointi Elastinen haku
  4. Etsi sovellusliittymän päätepiste

Kuten edellisessä artikkelissani, Kuinka parantaa suorituskykyäsi palvelimettomalla arkkitehtuurilla, käsittelen kaikkea vaiheittaisessa opetusohjelmassa. Sitten voit kokeilla sitä itse ja saada yksinkertaisen toimivan esimerkin, jolla rakentaa jotain monimutkaisempaa.

Esimerkkihakemuksesta tulee Elokuva-hakukone. Sillä on yksi JSON API -pääte, jonka avulla voit tehdä täyden tekstin haun elokuvien nimikkeistä ja katsauksista.

1. Elastisen haun asetukset

Elasticsearch on hajautettu, RESTful haku- ja analytiikkamoottori, joka pystyy ratkaisemaan kasvavan määrän käyttötapauksia. Joustavan pinon sydämenä, se tallentaa tietosi keskitetysti, jotta voit löytää odotetut ja paljastaa odottamattomat. - www.elastic.co/products/elasticsearch

DB-Enginesin hakukoneiden luokituksen mukaan Elasticsearch on ylivoimaisesti suosituin hakukonealusta (huhtikuusta 2018 alkaen). Ja se on ollut vuoden 2015 lopusta lähtien, kun Amazon ilmoitti AWS Elasticsearch -palvelun käynnistämisestä, tapa perustaa Elasticsearch-klusteri AWS Management -konsolista.

DB-moottorien hakukoneiden sijoitustrendit

Elastinen haku on avointa hankintaa. Voit ladata haluamasi version heidän verkkosivustoltaan ja käyttää sitä missä haluat. Ehdotan AWS Elasticsearch -palvelun käyttöä tuotantoympäristöissä, mutta suosittelen, että Elasticsearch toimii paikallisella koneellani testaamiseen ja kehittämiseen.

Aloitetaan lataamalla (tällä hetkellä) viimeisin Elasticsearch-versio (6.2.3) ja purkamalla se. Avaa pääte ja aja

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.3.zip
$ unzip Flexiblesearch-6.2.3.zip

Vaihtoehtoisesti voit ladata Elasticsearch -selaimesi täältä ja purkaa sen haluamallasi ohjelmalla.

2. Testaa ympäristöympäristö

Aiomme rakentaa taustasovelluksen Ruby on Rails 5 API: n avulla. Sillä on yksi malli, joka edustaa elokuvia. Elastinen haku indeksoi sen, ja sitä voidaan hakea API-päätepisteen kautta.

Ensinnäkin luodaan uusi kiskosovellus. Suorita samassa kansiossa, jonka olet aiemmin ladannut Elasticsearch, suorita komento uuden railsovelluksen luomiseksi. Jos olet uusi Ruby on Rails -yritys, määritä ympäristösi ensin tästä aloitusoppaasta.

$ rails uusia elokuvia -haku --api; CD-elokuvat -haku

Kun käytetään api-vaihtoehtoa, kaikkia pääasiassa selainsovelluksiin käytettäviä väliohjelmia ei sisällytetä. Juuri mitä haluamme. Lue lisää siitä suoraan rubiini kiskoilla -oppaasta.

Lisäämme nyt kaikki tarvitsemmemme jalokivet. Avaa Gemfile ja lisää seuraava koodi:

# Gemfile
...
# Elastisen haun integraatio
helmi 'elastinenhaku-malli'
helmi 'joustavahakukaiteet'
ryhmä: kehittäminen,: testit
  ...
  # Testikehys
  helmi 'rspec'
  helmi 'rspec-rails'
pää
ryhmä: testi tehdä
  ...
  # Puhdista tietokanta testien välillä
  helmi 'tietokantapuhdistin'
  # Käynnistä ja lopeta ohjelmoidusti ES testiä varten
  helmi 'elastinenhaku-laajennukset'
pää
...

Lisäämme kaksi Elasticsearch-jalokiviä, jotka tarjoavat kaikki tarvittavat menetelmät mallimme indeksoimiseksi ja hakukyselyjen suorittamiseksi siitä. Testaukseen käytetään rspec-, rspec-kiskoja, tietokantapuhdistusainetta ja elastisia haku-laajennuksia.

Kun olet tallentanut Gemfilesi, suorita paketin asennus asentaaksesi kaikki lisätyt jalokivet.

Määritetään nyt Rspec suorittamalla seuraava komento:

kiskot tuottavat rspec: asenna

Tämä komento luo spec-kansion ja lisää siihen spec_helper.rb ja rails_helper.rb. Niitä voidaan käyttää mukauttamaan rspec sovellustarpeisiisi.

Tässä tapauksessa lisäämme DatabaseCleaner-lohkon rails_helper.rb-tiedostoon, jotta jokainen testi suoritetaan tyhjään tietokantaan. Lisäksi modifioimme spec_helper.rb käynnistääksesi Elasticsearch-testipalvelimen joka kerta, kun testipaketti käynnistetään, ja sammuta se uudelleen, kun testipaketti on valmis.

Tämä ratkaisu perustuu Rowan Oultonin artikkeliin Elastisen haun testaaminen kiskoilla. Monet taputtaa häntä!

Aloitetaan DatabaseCleanerilla. Lisää spec / rails_helper.rb -koodiin seuraava koodi:

# spec / rails_helper.rb
...
RSpec.configure do | config |
  ...
config.before (: suite) tehdä
    DatabaseCleaner.strategy =: tapahtuma
    DatabaseCleaner.clean_with (: katkaisu)
  pää
config.around (: kukin) tee | esimerkki |
    DatabaseCleaner.puhdistus tehdään
      example.run
    pää
  pää
pää

Ajatellaan seuraavaksi Elasticsearch-testipalvelimen asennusta. Meidän on lisättävä joitain määritystiedostoja, jotta Rails tietää mistä löydät Elasticsearch-suoritettavan. Se kertoo myös nykyisessä ympäristössä, millä satamalla haluamme sen toimivan. Lisää uusi konfiguraatiojyvä konfiguraatiokansioon:

# config / Flexiblesearch.yml
kehitys: & oletus
  es_bin: '../elasticsearch-6.2.3/bin/elasticsearch'
  isäntä: 'http: // localhost: 9200'
  portti: '9200'
testata:
  es_bin: '../elasticsearch-6.2.3/bin/elasticsearch'
  isäntä: 'http: // localhost: 9250'
  portti: '9250'
lavastus:
  <<: * oletusasetus
tuotanto:
  es_bin: '../elasticsearch-6.2.3/bin/elasticsearch'
  isäntä: 'http: // localhost: 9400'
  portti: '9400'

Jos et ole luonut kiskosovellusta samassa kansiossa, josta latasit Elasticsearch, tai jos käytät eri versiota Elasticsearchista, sinun on mukautettava es_bin-polku tässä.

Lisää nyt uusi tiedosto alustuskansioon, joka lukee juuri lisäämästämme kokoonpanosta:

# config / alustajat / Flexiblesearch.rb
jos File.exists? ("config / Flexiblesearch.yml")
   config = YAML.load_file ("config / Flexiblesearch.yml") [Rails.env] .symbolize_keys
   Elastinen haku :: Model.client = Elastinen haku :: Client.new (config)
pää

Ja lopuksi muutamme spec_helper.rb sisällyttämään Elasticsearch-testin asetukset. Tämä tarkoittaa Elasticsearch-testipalvelimen käynnistämistä ja lopettamista ja Elasticsearch-hakemistojen luomista / poistamista Rails-mallillemme.

# spec / spec_helper.rb
vaadi 'joustavaa hakua / laajennuksia / testiä / klusteria'
vaatia 'yaml'
RSpec.configure do | config |
  ...
  # Käynnistä Elastinen haku -muistiklusteri tarvittaessa
  es_config = YAML.load_file ("config / Flexiblesearch.yml") ["test"]
  ES_BIN = es_config ["es_bin"]
  ES_PORT = es_config ["portti]]
config.before: kaikki, elastinenhaku: totta
    Elastinen haku :: Laajennukset :: Testi :: Cluster.start (komento: ES_BIN, portti: ES_PORT.to_i, solmut: 1, aikakatkaisu: 120), ellei Elasticsearch :: Laajennukset :: Testi :: Cluster.running? (Komento: ES_BIN, päällä: ES_PORT.to_i)
  pää
# Pysäytä elastisen haun klusteri koeajon jälkeen
  config.after: suite do
    Elasticsearch :: Laajennukset :: Test :: Cluster.stop (komento: ES_BIN, portti: ES_PORT.to_i, solmut: 1) jos Elasticsearch :: Laajennukset :: Test :: Cluster.running? (Komento: ES_BIN, päällä: ES_PORT. to_i)
  pää
# Luo hakemistot kaikille joustaville haettavissa oleville malleille
  config.before: kukin, elastinen haku: totta
    ActiveRecord :: Base.descendants.each do | malli |
      jos malli.vastaa_to? (: __ elastinenhaku__)
        alkaa
          Mallin .__ elasticsearch __. create_index!
          Mallin .__ elasticsearch __. refresh_index!
        pelastus => Elastinen haku :: Kuljetus :: Kuljetus :: Virheet :: NotFound
          # Tämä tappaa "Indeksiä ei ole" -virheitä kirjoitettaessa konsoliin
        pelastus => e
          STDERR.puts "Virhe luotaessa joustavan hakuhakemiston mallille # {malli.nimi}: # {e.inspect}"
        pää
      pää
    pää
  pää
# Poista kaikkien joustavien haettavien mallien hakemistot puhtaan tilan varmistamiseksi testien välillä
  config.after: kukin, joustavahaku: true do
    ActiveRecord :: Base.descendants.each do | malli |
      jos malli.vastaa_to? (: __ elastinenhaku__)
        alkaa
          Mallin .__ elasticsearch __. delete_index!
        pelastus => Elastinen haku :: Kuljetus :: Kuljetus :: Virheet :: NotFound
          # Tämä tappaa "Indeksiä ei ole" -virheitä kirjoitettaessa konsoliin
        pelastus => e
          STDERR.puts "Virhe poistettaessa # {malli.nimi} joustavan hakuindeksin: # {e.inspect}"
        pää
      pää
    pää
  pää
pää

Olemme määritelleet neljä lohkoa:

  1. a ennen (: kaikki) lohko, joka käynnistää Elasticsearch-testipalvelimen, ellei se ole jo käynnissä
  2. jälkeenoleva (: suite) -lohko, joka pysäyttää Elasticsearch-testipalvelimen, jos se on käynnissä
  3. a ennen (: jokainen) lohko, joka luo uuden Elastinen haku -hakemiston jokaiselle mallelle, joka on määritetty Elasticsearchilla
  4. jälkeinen (: kukin) lohko, joka poistaa kaikki Elastinen haku -indeksit

Elastisen haun lisääminen: true varmistaa, että vain elastisen haun avulla koodatut testit suorittavat nämä lohkot.

Mielestäni tämä asennus toimii hyvin, kun suoritat kaikki testit kerran, esimerkiksi ennen käyttöönottoa. Toisaalta, jos käytät testilähtöistä kehitystyötä ja suoritat testit hyvin usein, sinun on todennäköisesti muutettava tätä kokoonpanoa hieman. Et halua käynnistää ja pysäyttää Elasticsearch-testipalvelinta jokaisessa koekäytössä.

Tässä tapauksessa voit kommentoida jälkeen (: suite) -lohkon, jossa testipalvelin on pysäytetty. Voit sammuttaa sen manuaalisesti tai komentosarjan avulla, kun et enää tarvitse sitä.

vaadi 'joustavaa hakua / laajennuksia / testiä / klusteria'
es_config = YAML.load_file ("config / Flexiblesearch.yml") ["test"]
ES_BIN = es_config ["es_bin"]
ES_PORT = es_config ["portti]]
Elastinen haku :: Laajennukset :: Testi :: Cluster.stop (komento: ES_BIN, portti: ES_PORT.to_i, solmut: 1)

3. Mallien indeksointi elastisella haulla

Nyt aloitamme elokuvamallimme toteuttamisen hakuominaisuuksilla. Käytämme Test Driven Development -lähestymistapaa. Tämä tarkoittaa, että kirjoitamme ensin testit, näemme niiden epäonnistuvan ja kirjoitamme sitten koodin, jotta ne läpäisivät.

Ensin on lisättävä elokuvamalli, jolla on neljä ominaisuutta: otsikko (merkkijono), kuvaus (teksti), image_url (merkkijono) ja keskimääräinen ääniarvo (kelluva).

$ rails g model Elokuvan nimi: merkkijonon kuvaus: tekstin kuva_url: merkkijono äänten keskiarvo: kelluva
$ rails db: siirtyä

Nyt on aika lisätä Elasticsearch malliin. Kirjoitakoe, joka tarkistaa, että mallimme on indeksoitu.

# spec / mallit / movie_spec.rb
vaadi 'rails_helper'
RSpec.describe Elokuva, joustavahaku: totta,: type =>: model do
  se 'pitäisi indeksoida' tehdä
     odottaa (elokuvan .__ elastinen haku __. hakemisto_kehittyy?) .todellisuutta
  pää
pää

Tämä testi tarkistaa, onko elokuvalle luotu elastinen hakuindeksi. Muista, että ennen testien alkamista luomme automaattisesti joustavan hakuindeksin kaikille malleille, jotka vastaavat __elastinenhaku__ -menetelmään. Tämä tarkoittaa kaikkia malleja, jotka sisältävät joustavat hakuyksiköt.

Suorita testi nähdäksesi sen epäonnistuvan.

kimppu suorita rspec spec / models / movie_spec.rb

Kun teet tämän testin ensimmäisen kerran, sinun pitäisi nähdä, että Elasticsearch Test Server on käynnistymässä. Testi epäonnistuu, koska emme lisänneet mitään Elastinen haku -moduulia elokuvamallillemme. Korjaa se nyt. Avaa malli ja lisää seuraava Elastinen haku:

# sovellus / mallit / movie.rb
luokan elokuva 

Tämä lisää elokuvamalliimme joitain Elastinenhaku-menetelmiä, kuten puuttuva __elastinenhaku__ -menetelmä (joka aiheutti virheen edellisessä testiajoissa) ja hakumenetelmä, jota käytämme myöhemmin.

Suorita testi uudelleen ja näe sen läpäisevän.

kimppu suorita rspec spec / models / movie_spec.rb

Loistava. Meillä on indeksoitu elokuvamalli.

Oletuksena Elasticsearch :: Model asettaa hakemiston kaikilla mallin määritteillä, päättäen automaattisesti niiden tyypit. Yleensä tämä ei ole mitä haluamme. Mukautamme nyt malli-hakemistoa siten, että se käyttäytyy seuraavasti:

  1. Vain otsikko ja yleiskatsaus tulisi indeksoida
  2. Stemmingiä tulisi käyttää (mikä tarkoittaa, että ”näyttelijöiden” etsimisen pitäisi myös palauttaa elokuvat, joissa on teksti “näyttelijä”, ja päinvastoin)

Haluamme myös hakemistomme päivityksen joka kerta, kun elokuva lisätään, päivitetään tai poistetaan.

Käännetään tämä testiiksi lisäämällä seuraava koodi elokuvan_spec.rb-kohtaan

# spec / mallit / movie_spec.rb
RSpec.describe Elokuva, joustavahaku: totta,: type =>: model do
  ...
kuvaile 'haun' tekemistä
    ennen (: kukin) tekevät
      Movie.create (
        nimi: "Rooman loma",
        katsaus: "Vuoden 1953 amerikkalainen romanttinen komediaelokuva ...",
        image_url: "wikimedia.com/Roman_holiday.jpg",
        äänten keskiarvo: 4,0
      )
      Elokuva .__ elasticsearch __. Refresh_index!
    pää
    sen "pitäisi indeksoida otsikko" tehdä
      odottaa (Movie.search ("Loma"). Records.length) .to eq (1)
    pää
    sen "pitäisi indeksoida yleiskatsaus" tehdä
      odottaa (Elokuva.haku ("komedia"). ennätys.pituus) .to eq (1)
    pää
    sen "ei pitäisi indeksoida kuvapolkua"
      odottaa (Movie.search ("Roman_holiday.jpg"). records.length) .to eq (0)
    pää
    sen "ei pitäisi indeksoida äänimäärää"
      odottaa (Movie.search ("4.0"). Records.length) .to ekv (0)
    pää
  pää
pää

Luomme elokuvan ennen kutakin testiä, koska määritimme DatabaseCleanerin siten, että jokainen testi on eristetty. Elokuva .__ elasticsearch __. Refresh_index! tarvitaan, jotta voidaan varmistaa, että uusi elokuvalevy on heti saatavissa hakua varten.

Suorita testi kuten aiemmin ja katso, että se epäonnistuu.

Näyttää siltä, ​​että elokuvaa ei indeksoida. Tämä johtuu siitä, ettemme vielä kertoneet mallillemme, mitä tehdä, kun elokuvan tiedot muuttuvat. Onneksi tämä voidaan korjata lisäämällä toinen moduuli elokuvamalliimme:

luokan elokuva 

Elasticsearch :: Model :: Callbacks -sovelluksella päivitetään myös elokuvaa päivitettäessä, kun sitä lisätään, muutetaan tai poistetaan.

Katsotaan kuinka testitulos muuttuu.

Ok. Nyt ongelmana on, että hakumenetelmämme palauttaa myös kyselyt, jotka vastaavat määritteitä äänestysarvo ja kuva_url. Korjataksesi tämä, meidän on määritettävä Elasticsearch-indeksikartoitus. Joten meidän on kerrottava Elasticsearchille, mikä malli määrittelee indeksin.

# sovellus / mallit / movie.rb
luokan elokuva 
# Elastinen hakuhakemisto
  asetushakemisto: {number_of_shards: 1} tehdä
    kuvaukset dynaamisesti: 'väärät' tekevät
      hakemistot: otsikko
      hakemistot: yleiskatsaus
    pää
  pää
pää

Suorita testi uudelleen ja näe sen läpäisevän.

Viileä. Lisäämme nyt varren, jotta näyttelijöiden ja näyttelijöiden välillä ei olisi eroa. Kuten aina, kirjoitamme testin ensin ja näemme sen epäonnistuvan.

kuvaile 'haun' tekemistä
    ennen (: kukin) tekevät
      Movie.create (
        nimi: "Rooman loma",
        katsaus: "Vuoden 1953 amerikkalainen romanttinen komediaelokuva ...",
        image_url: "wikimedia.com/Roman_holiday.jpg",
        äänten keskiarvo: 4,0
      )
      Elokuva .__ elasticsearch __. Refresh_index!
    pää
...
sitä "tulisi soveltaa otsikkoon",
      odottaa (Movie.search ("Lomat"). Records.length) .to eq (1)
    pää
sitä "pitäisi soveltaa johtuen yleiskatsaukseen"
      odottaa (Elokuva.haku ("elokuva"). ennätyspituus) .toeq (1)
    pää
pää

Huomaa, että testaamme molempia tapoja: Lomien pitäisi palauttaa myös Lomat ja Elokuvien tulisi palauttaa myös Elokuvat.

Jotta nämä testit läpäisivät uudelleen, meidän on muokattava indeksikartoitusta. Teemme sen tällä kertaa lisäämällä kumpaankin kenttään englanninkielisen analysaattorin:

luokan elokuva 
# Elastinen hakuhakemisto
  asetushakemisto: {number_of_shards: 1} tehdä
    kuvaukset dynaamisesti: 'väärät' tekevät
      hakemistot: otsikko, analysaattori: 'englanti'
      hakemistot: yleiskatsaus, analysaattori: 'englanti'
    pää
  pää
pää

Suorita testit uudelleen nähdäksesi niiden läpäisevän.

Elasticsearch on erittäin tehokas hakualusta, ja voisimme lisätä paljon toimintoja hakumenetelmäämme. Mutta tämä ei kuulu tämän artikkelin soveltamisalaan. Joten pysähdymme tähän ja siirrymme eteenpäin JSON-sovellusliittymän ohjainosan rakentamiseen, jonka kautta hakutapaa käytetään.

4. Etsi API-päätepiste

Rakentamastamme haku-sovellusliittymän tulisi antaa käyttäjille mahdollisuus tehdä täyden tekstin haku elokuvataulusta. Sovellusliittymämme on yksi päätepiste määritetty seuraavasti:

url:
 GET / api / v1 / elokuvat
params:
 * q = [merkkijono] vaaditaan
Esimerkki URL:
 GET / api / v1 / elokuvat? Q = romanit
Esimerkki vastauksesta:
[{ "_Index": "elokuvat", "_ tyyppi": "elokuva", "_ id": "95088", "_ pisteet": 11,549209, "_ lähde": { "id": 95088, "otsikko": "Roma" , "yleiskatsaus": "Lähes juonivapaa, haalea ja impressionistinen muotokuva Roomasta yhden sen kuuluisimpien kansalaisten silmissä.", "image_url": "https://image.tmdb.org/t/p/w300/ rqK75R3tTz2iWU0AQ6tLz3KMOU1.jpg", "vote_average": 6,6, "created_at": "2018-04-14T10: 30: 49.110Z", "updated_at": "2018-04-14T10: 30: 49.110Z"}}, ... ]

Määrittelemme tässä päätepisteemme joidenkin parhaiden käytäntöjen mukaan RESTful API Design:

  1. URL-osoitteen tulee koodata objekti tai resurssi, kun taas suoritettavat toimenpiteet tulisi koodata HTTP-menetelmällä. Tässä tapauksessa resurssi on elokuvat (kokoelma) ja käytämme HTTP-menetelmää GET (koska pyydämme tietoja resurssista tuottamatta sivuvaikutuksia). Käytämme URL-parametreja määritelläksesi tarkemmin, miten nämä tiedot tulisi hankkia. Tässä esimerkissä q = [merkkijono], joka määrittelee hakukyselyn. Voit lukea lisää RESTful-sovellusliittymien suunnittelusta Mahesh Haldarin artikkelissa RESTful API -suunnitteluohjeet - parhaat käytännöt.
  2. Lisäämme myös versioinnin sovellusliittymäämme lisäämällä v1 päätepisteen URL-osoitteeseen. Sovellusliittymän versiointi on erittäin tärkeää, koska sen avulla voit ottaa käyttöön uusia ominaisuuksia, jotka eivät ole yhteensopivia aiempien julkaisujen kanssa, rikkomatta kaikkia asiakkaita, jotka on kehitetty sovellusliittymäsi aiemmille versioille.

Ok. Aloitetaan toteuttaminen.

Kuten aina, aloitamme epäonnistuneilla testeillä. Spec-kansion sisällä luomme kansiorakenteen, joka heijastaa API-päätepisteen URL-rakennetta. Tämä tarkoittaa ohjaimia → api → v1 → movies_spec.rb

Voit tehdä tämän manuaalisesti tai päätelaitteestasi:

mkdir -p spec / ohjaimet / api / v1 &&
kosketa spec / ohjaimet / api / v1 / movies_spec.rb

Testit, jotka aiomme kirjoittaa tänne, ovat ohjaustestit. Niiden ei tarvitse tarkistaa mallissa määritettyä hakulogiikkaa. Sen sijaan testaamme kolme asiaa:

  1. GET-pyyntö hakemistoon / api / v1 / movies? Q = [merkkijono] soittaa Movie.search-parametriksi [merkkijono] parametrina
  2. Movie.search-tulosteet palautetaan JSON-muodossa
  3. Menestystila palautetaan
Ohjaimen testin tulisi testata ohjaimen käyttäytyminen. Ohjaintesti ei saisi epäonnistua mallin ongelmien vuoksi.
(Reseptilääke 20 - Kiskot 4 Testimääräystä. Noel Rappin)

Muutetaan tämä koodiksi. Lisää spec-ohjaimet / ohjaimet / api / v1 / movies_spec.rb seuraava koodi:

# spec / ohjaimet / api / v1 / movies_spec.rb
vaadi 'rails_helper'
RSpec.describe Api :: V1 :: MoviesController, tyyppi:: request do
  # Etsi elokuvaa, jolla on elokuvan otsikko
  kuvaile "GET / api / v1 / movies? q =" do
    anna (: otsikko) {"movie-title"}
    let (: url) {"/ api / v1 / movies? q = # {title}"}
se "kutsuu Movie.searchia oikeilla parametreilla" do
      odottaa (elokuva) .vastaanota (: haku). kanssa (otsikko)
      hanki URL
    pää
se "palauttaa Movie.search-tulosteen" do
      Salli (Elokuva) .vastaanottaa (: etsi) .ja palauta ({})
      hanki URL
      odottaa (vastaus. henkilö) .to eq ({}. to_json)
    pää
se 'palauttaa menestystilan' tehdä
      Salli (Elokuva). vastaanottaa (: etsi). kanssa (otsikko)
      hanki URL
      odottaa (vastaus) .on onnistunut
    pää
  pää
pää

Testi epäonnistuu heti, koska Api :: V1 :: MoviesController -sovellusta ei ole määritelty, joten tehdään ensin. Luo kansiorakenne kuten aiemmin ja lisää elokuvien ohjain.

mkdir -p sovellus / ohjaimet / api / v1 &&
kosketa sovellusta / ohjaimia / api / v1 / movies_controller.rb

Lisää nyt seuraava koodi sovellukseen / ohjaimiin / api / v1 / movies_controller.rb:

# sovellus / ohjaimet / api / v1 / movies_controller.rb
moduuli Api
  moduuli V1
    luokan MoviesController 

On aika suorittaa testi ja nähdä sen epäonnistuvan.

Kaikki testit epäonnistuvat, koska meidän on vielä lisättävä reitti päätepisteeseen. Lisää seuraava koodi koodiin config / route.rb: n sisään:

# config / route.rb
Rails.application.routes.draw tehdä
  nimitila: api do
    nimitila: v1 tehdä
      resurssit: vain elokuvat: [: hakemisto]
    pää
  pää
pää

Suorita testit ja katso mitä tapahtuu.

Ensimmäinen virhe kertoo, että meidän on lisättävä puhelu Movie.search-ohjaimeen. Toinen valittaa vastauksesta. Lisätään puuttuva koodi movies_controller:

# sovellus / ohjaimet / api / v1 / movies_controller.rb
moduuli Api
  moduuli V1
    luokan MoviesController 

Suorita testi ja katso onko valmis.

Jep. Siinä kaikki. Olemme valmistaneet todella perustana olevan taustasovelluksen, jonka avulla käyttäjät voivat etsiä mallia sovellusliittymän kautta.

Löydät täydellisen koodin GitHub-repo-sivustoltasi täältä. Voit täyttää elokuvataulukon jollain datalla suorittamalla kiskot db: siemen, jotta näet sovelluksen toiminnassa. Tämä tuo noin 45 kt elokuvia Kagglesta ladatusta tietojoukosta. Katso lisätietoja Readmestä.

Jos nautit tästä artikkelista, suosittele sitä napsauttamalla tämän sivun alalaidasta löytyvää apunakuvaketta, jotta useammat ihmiset voivat nähdä sen keskipitkällä.