(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': data().getTime(),įvykis:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); Papildomų išteklių įtraukimas į REST tipo API - The Codest
The Codest
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Pramonės šakos
    • Fintech ir bankininkystė
    • E-commerce
    • Adtech
    • Sveikatos technologijos
    • Gamyba
    • Logistika
    • Automobiliai
    • IOT
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
Atgal rodyklė GRĮŽTI ATGAL
2022-03-22
Programinės įrangos kūrimas

Papildomų išteklių įtraukimas į REST tipo API

The Codest

Krzysztof Buszewicz

Vyresnysis Software Engineer

Sukursime knygų lentynos programą, kuri leis sudaryti knygų sąrašą su autorių duomenimis (arba be jų).

Ką darysime?

Sukursime knygų lentynos programėlę, kuri leis sudaryti knygų sąrašą su autoriais (arba be jų). duomenys. Bus vienas #index veiksmų ir kai kurių sėklų. Tai bus pavyzdinė programa, kurioje parodysime, kaip galima suteikti naudotojui galimybę valdyti įtrauktus sub-šaltinių REST tipo API.

“Priėmimo kriterijai”

  • Naudotojas gali sudaryti knygų sąrašą.
  • Naudotojas gali perduoti apima užklausos parametras, kad būtų įkelti susiję ištekliai (autorius).
  • apima užklausos parametro formatas yra eilutė: kableliais atskirti žodžiai, reiškiantys įterptus išteklius.
  • Turėtume turėti tam tikras konstantas, apibrėžiančias, kurie ištekliai gali būti įtraukti į kurį veiksmą.

Įrankiai

Naudosime mėlynasis spausdintuvas kaip serializatorių, nes jis nepriklauso nuo formato ir yra gana lankstus. Tai vienintelis brangakmenis, kuriuo papildysime standartinį rails įrankių rinkinį.

Programėlė

Sukurkime pavyzdinę programą. Testų sistemos nepridėsime, nes tai neįeina į mūsų taikymo sritį.

bėgiai nauja knygų lentyna -T

Dabar sukurkite Autorius modelis:

rails g modelio autoriaus vardas:string
#=> invoke active_record
#=> create db/migrate/20211224084524_create_authors.rb
#=> create app/models/author.rb

Ir Knyga:

rails g modelis knyga autorius:nuorodos pavadinimas:string
# => invoke active_record
# => create db/migrate/20211224084614_create_books.rb
# => create app/models/book.rb

Mums reikės sėklų:

# db/seeds.rb

dumas = Author.create(vardas: 'Alexandre Dumas')
lewis = Author.create(vardas: 'C.S. Lewis')
martin = Author.create(vardas: 'Robert C. Martin')

Book.create(autorius: dumas, pavadinimas: 'Trys muškietininkai')
Book.create(autorius: lewis, pavadinimas: 'The Lion, the Witch and the Wardrobe')
Book.create(autorius: martin, pavadinimas: 'Clean Code')

Dabar esame pasiruošę paleisti migracijas ir įdiegti db:

rails db:migrate && rails db:seed

Pridėkime has_many knygų Autorius modelis:

# app/models/author.rb

klasė Author < ApplicationRecord
  has_many :books
end

Laikas parašyti valdiklį, kuris grąžins mūsų duomenis. Naudosime API vardų erdvę, todėl pirmiausia pridėkime santrumpą prie skiemenų:

# config/initializers/inflections.rb

ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'API'
end

Gerai, pridėkime savo serializatorių prie Gemfile:

# Pridėti prie brangakmenių rinkmenos

gem 'blueprinter'

Ir, žinoma, jį įdiekite:

įdiegti paketą

Tada galėsime kurti savo planus:

# app/blueprints/author_blueprint.rb

klasė AuthorBlueprint < Blueprinter::Base
  identifikatorius :id

  laukai :name
end
# app/blueprints/book_blueprint.rb

klasė BookBlueprint < Blueprinter::Base
  identifikatorius :id

  laukai :title

  asociacija :author, blueprint: AuthorBlueprint
pabaiga

Pridėti bazinį valdiklį API:

# app/controllers/api/v1/base_controller.rb

API modulis
  modulis V1
    klasė BaseController < ActionController::API
    pabaiga
  end
end

Ir mūsų projekto versija BooksController:

# app/controllers/api/v1/books_controller.rb

API modulis
  modulis V1
    klasė BooksController < BaseController
      def index
        books = Book.all

        atvaizduoti json: BookBlueprint.render(books)
      end
    end
  end
end

Žinoma, taip pat turime apibrėžti maršruto parinkimą:

# config/routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :books, only: :index
    end
  end
end

Patikrinkime, ką iki šiol padarėme:

bėgiai s 
garbanoti http://localhost:3000/api/v1/books

# => [{"id":1, "author":{"id":1, "name": "Alexandre Dumas"}, "title": "Trys muškietininkai"},{"id":2, "author":{"id":2, "name": "C.S. Lewis"}, "pavadinimas": "The Lion, the Witch and the Wardrobe"},{"id":3, "autorius":{"id":3, "vardas": "Robert C. Martin"}, "pavadinimas": "Clean Kodas"}]

Atrodo, kad duomenys yra tvarkingi, o kaip su žurnalais?

# užklausų žurnalai (n+1)

Pradėta GET "/api/v1/books" 127.0.0.1 2021-12-24 10:19:40 +0100
API::V1::BooksController#index apdorojama kaip */*
  Knygų įkėlimas (0,1 ms) SELECT "books".* FROM "books"
  ↳ app/controllers/api/v1/books_controller.rb:7:in `index'
  Autorių įkėlimas (0.1 ms) SELECT "authors".* FROM "authors" WHERE "authors". "id" = ? LIMIT ?  [[["id", 1], ["LIMIT", 1]]]
  ↳ app/controllers/api/v1/books_controller.rb:7:in `in index'
  Autorių įkėlimas (0.1 ms) SELECT "authors".* FROM "authors" WHERE "authors". "id" = ? LIMIT ?  [[["id", 2], ["LIMIT", 1]]]
  ↳ app/controllers/api/v1/books_controller.rb:7:in `in index'
  Autorių įkėlimas (0.1 ms) SELECT "authors".* FROM "authors" WHERE "authors". "id" = ? LIMIT ?  [[["id", 3], ["LIMIT", 1]]]
  ↳ app/controllers/api/v1/books_controller.rb:7:in `in index'
Užbaigta 200 OK per 6 ms (Peržiūros: 0,1 ms | ActiveRecord: 0,4 ms | Alokacijos: 3134)

Naudodami asociaciją savo serializatoriuose įvedėme n+1 problema. Norime ją pašalinti suteikdami vartotojui galimybę kontroliuoti, ko jis prašo šiame galutiniame taške. Taigi jis turėtų galėti įkelti tik knygas arba perduoti parametrą includes ir gauti autorius, bet pageidautina be n+1.

Apibrėžkime konstantą, kuri saugos informaciją apie tai, kokius knygų asocijuotuosius narius vartotojas gali įtraukti į books#index veiksmai:

# lib/constants/books/includes.rb

modulis Constants
  modulis Books
    modulis Includes
      ALLOWED = {
        indeksas: %i[
          autorius
        ].freeze
      }.freeze
    pabaiga
  pabaiga
end

Toliau apibrėžiame vardų erdvę, skirtą tuščių objektų konstantoms:

# lib/constants/empty.rb

modulis Constants
  modulis Empty
    HASH = {}.freeze
  pabaiga
pabaiga

O štai mūsų pagrindinė leidimų išdavimo paslauga apima. Manau, kad kodas yra gana aiškus, kai kurios dalys magija skiriami tik #default_resources_key ir #default_purpose. Šie metodai apibrėžti tam, kad būtų galima mus iškviesti leidimą apima tik params perdavimą rails valdikliuose. Išvestis bus hash, kuriame saugoma tiesa kiekvienam leidžiamam įtraukimui.

# app/services/permit_includes.rb

require 'constants/empty'
require 'constants/books/includes'

klasė PermitIncludes
  Empty = Constants::Empty

  COMMA = ','
  SLASH = '/'

  INCLUDES_FORMAT = /A[a-z]+(,[a-z]+)*z/.freeze
  ALLOWED_INCLUDES = {
    books: Constants::Books::Includes::ALLOWED
  }.freeze

  def call(params, resources: default_resources_key(params), purpose: default_purpose(params))
    return Empty::HASH unless includes_sent?(params)
    return Empty::HASH unless includes_valid?(params)

    requested_includes = parse_includes(params)
    allowed_includes = filter_includes(requested_includes, resources, purpose)

    allowed_includes.index_with(true)
  pabaiga

  privatus

  def default_resources_key(params)
    raise(ArgumentError, 'params :controller key must be a string') unless params[:controller].is_a?(String)

    params[:controller].split(SLASH).last&.to_sym
  end

  def default_purpose(params)
    raise(ArgumentError, 'params :action key must be a string') unless params[:action].is_a?(String)

    params[:action].to_sym
  end

  def includes_sent?(params)
    params.key?(:includes)
  end

  def includes_valid?(params)
    return false nebent params[:includes].is_a?(String)

    params[:includes].match?(INCLUDES_FORMAT)
  end

  def parse_includes(params)
    params[:includes].split(COMMA).map(&:to_sym)
  end

  def filter_includes(requested_includes, resources_key, purpose)
    requested_includes & ALLOWED_INCLUDES[resources_key][purpose]
  end
end

Dabar turime naudoti raktus, kad įkeltume "Includes" ir perduotume patį "Inlcudes" hash serijalizatoriui:

# app/controllers/api/v1/books_controller.rb

API modulis
  modulis V1
    klasė BooksController < BaseController
      def index
        includes = PermitIncludes.new.call(params)
        books = Book.includes(includes.keys).all

        atvaizduoti json: KnygosBlueprint.render(books, includes: includes)
      pabaiga
    end
  end
end

Būtent taip turime pritaikyti savo serializatorių - asociaciją įkeliame tik tuo atveju, jei ji įtraukta:

# app/blueprints/book_blueprint.rb
klasė BookBlueprint (_field_name, _book, options) {
                         options[:includes] && options[:includes][:author]
                       }
end

Išbandykime tai dar kartą:

bėgiai s
garbanoti http://localhost:3000/api/v1/books
# => [{"id":1, "title": "Trys muškietininkai"},{"id":2, "title": "Liūtas, ragana ir drabužių spinta"},{"id":3, "title": "Švarus kodas"}]
# užklausų žurnalai (įkeliame tik knygas)
Pradėta GET "/api/v1/knygos" ::1 2021-12-24 10:33:41 +0100
API::V1::BooksController#index apdorojama kaip */*
   (0.1 ms) SELECT sqlite_version(*)
  ↳ app/controllers/api/v1/books_controller.rb:8:in `index'
  Knygų įkėlimas (0.1 ms) SELECT "books".* FROM "books"
  ↳ app/controllers/api/v1/books_controller.rb:8:in `index'
Užbaigta 200 OK per 9 ms (Peržiūros: 0,1 ms | ActiveRecord: 0,9 ms | Alokacijos: 4548)

Gerai, mes neperdavė apima, todėl gavo tik knygas, be autorių. Dabar jų paprašykime:

curl 'http://localhost:3000/api/v1/books?includes=author'
# => [{"id":1, "author":{"id":1, "name": "Alexandre Dumas"}, "title": "Trys muškietininkai"},{"id":2, "author":{"id":2, "name": "C.S. Lewis"}, "title": "The Lion, the Witch and the Wardrobe"},{"id":3, "author":{"id":3, "name": "Robert C. Martin"}, "title": "Clean Code"}]% 
# užklausų žurnalai (pašalinta n+1)

Pradėta GET "/api/v1/books?includes=author" ::1 2021-12-24 10:38:23 +0100
API::V1::BooksController#index apdorojama kaip */*
  Parametrai: {"includes"=>"author"}
  Knygos įkėlimas (0,1 ms) SELECT "books".* FROM "books"
  ↳ app/controllers/api/v1/books_controller.rb:8:in `in index'
  Autorių įkėlimas (0.2 ms) SELECT "authors".* FROM "authors" WHERE "authors". "id" IN (?, ?, ?) [["id", 1], ["id", 2], ["id", 3]]]
  ↳ app/controllers/api/v1/books_controller.rb:8:in `in index'
Užbaigta 200 OK per 17 ms (Peržiūros: 0,1 ms | ActiveRecord: 0,7 ms | Alokacijos: 7373)

Šaunu! Asociacija įkelta ir pašalinta n+1 problema. Paslauga gali būti naudojama bet kokiam ištekliui, viskas, ką norime padaryti, tai pridėti leistinas konstantas tinkamu formatu ir pridėti jas prie PermitIncludes::ALLOWED_INCLUDES.

Reikia nepamiršti, kad šią funkciją tikriausiai reikėtų naudoti kartu su puslapiais (ir atsargiai), nes asociacijų įtraukimas gali “suvalgyti” daug atminties.

Susiję straipsniai

Programinės įrangos kūrimas

5 geriausi "Ruby" naudojimo pavyzdžiai

Ar kada nors susimąstėte, ką galime padaryti su "Ruby"? Ko gero, dangus yra beribis, bet mes mielai papasakosime apie kai kuriuos daugiau ar mažiau žinomus atvejus...

The Codest
Pawel Muszynski Software Engineer
Programinės įrangos kūrimas

Polimorfizmas "Ruby" ir "GraphQL" kalbose

Šiame straipsnyje pristatysiu polimorfizmo naudojimą GraphQL. Tačiau prieš pradedant verta priminti, kas yra polimorfizmas ir GraphQL.

Lukasz Brzeszcz
Programinės įrangos kūrimas

Kibernetinio saugumo dilemos: Duomenų nutekėjimas

Prieššventinis skubėjimas įsibėgėja. Ieškodami dovanų savo artimiesiems, žmonės vis dažniau ryžtasi "šturmuoti" internetines parduotuves.

The Codest
Jakubas Jakubovičius CTO ir vienas iš įkūrėjų
Programinės įrangos kūrimas

Paprasta "Ruby" programa nuo nulio su "Active Record

MVC - tai projektavimo modelis, kuriuo padalijamos taikomosios programos pareigos, kad ją būtų lengviau valdyti. Rails pagal susitarimą laikosi šio projektavimo modelio.

The Codest
Damianas Watroba Software Engineer

Prenumeruokite mūsų žinių bazę ir būkite nuolat informuoti apie IT sektoriaus patirtį.

    Apie mus

    The Codest - tarptautinė programinės įrangos kūrimo bendrovė, turinti technologijų centrus Lenkijoje.

    Jungtinė Karalystė - būstinė

    • 303B biuras, 182-184 High Street North E6 2JA
      Londonas, Anglija

    Lenkija - vietiniai technologijų centrai

    • Fabryczna biurų parkas, Aleja
      Pokoju 18, 31-564 Krokuva
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšuva, Lenkija

    The Codest

    • Pagrindinis
    • Apie mus
    • Paslaugos
    • Case Studies
    • Sužinokite, kaip
    • Karjera
    • Žodynas

    Paslaugos

    • Patariamoji tarnyba
    • Programinės įrangos kūrimas
    • Galinės dalies kūrimas
    • Priekinės dalies kūrimas
    • Staff Augmentation
    • Atgalinės versijos kūrėjai
    • Debesų inžinieriai
    • Duomenų inžinieriai
    • Kita
    • QA inžinieriai

    Ištekliai

    • Faktai ir mitai apie bendradarbiavimą su išoriniu programinės įrangos kūrimo partneriu
    • Iš JAV į Europą: Kodėl Amerikos startuoliai nusprendžia persikelti į Europą?
    • Technikos plėtros centrų užsienyje palyginimas: Tech Offshore Europa (Lenkija), ASEAN (Filipinai), Eurazija (Turkija)
    • Kokie yra svarbiausi CTO ir CIO iššūkiai?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Autorinės teisės © 2026 The Codest. Visos teisės saugomos.

    lt_LTLithuanian
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian is_ISIcelandic lt_LTLithuanian