Gem-creatie met Bundler

Het bouwen van een edelsteen was vroeger een complexe taak waarvoor een exacte kennis van het edelsteenformaat, zelf of een aantal speciale gereedschappen nodig was om een ​​geschikte boilerplate te genereren. Tegenwoordig kunnen we de uitstekende Bundler gebruiken om deze complexiteit te verwijderen en de hoeveelheid gegenereerde code tot een minimum te beperken.


Wat we bouwen

Het testpareltje dat we gaan bouwen, is een dummy content-generator die je misschien zou kunnen gebruiken tijdens de ontwikkeling. In plaats van het genereren van "Lorem ipsum" -zinnen, gebruikt het Dracula van Bram Stoker om een ​​willekeurig aantal zinnen uit het boek te halen. Onze workflow begint met het genereren van het juweel, het testen en implementeren van de minimale hoeveelheid code die nodig is om ons juweeltje gereed te maken en het vervolgens te publiceren op RubyGems.


Een skelet genereren

Ik ga ervan uit dat je al een Ruby-omgeving hebt ingesteld. Voor deze zelfstudie gebruiken we Ruby 1.9.3 als een basislijn. Als u echter van plan bent een echt juweeltje te ontwikkelen, is het misschien goed om het ook te testen tegen Ruby 1.8 en andere tolken. Voor dat doel is een tool als Travis CI een uitkomst; met een solide testsuite op zijn plaats laat Travis u uw juweel zonder veel moeite testen op een breed scala aan platforms. Laten we beginnen met het genereren van het skelet:

bundel edelsteen bramipsum

Het spijt me heel erg als je de naam die ik kies niet leuk vindt, het is een van de moeilijkste taken bij het ontwikkelen van een edelsteen om de juiste naam te vinden. De opdracht maakt een map met de naam bramipsum met een paar bestanden:

Gemfile

Het Gemfile is erg minimaal:

bron 'http://rubygems.org' # Geef de afhankelijkheden van uw edelsteen op in bramipsum.gemspec gemspec

Merk op dat het duidelijk aangeeft dat je de afhankelijkheden van edelstenen moet verplaatsen naar bramipsum.gemspec, om alle relevante gegevens voor je edelsteen in het bestand te hebben dat zal worden gebruikt om de metadata op Rubygems te vullen.

bramipsum.gemspec

De gemspec bestand bevat veel informatie over ons juweeltje; we kunnen zien dat het zwaar afhankelijk is van Git om de juiste waarden toe te wijzen aan alle variabelen die betrekking hebben op bestandsvermelding.

# - * - codering: utf-8 - * - vereisen File.expand_path ('... / lib / bramipsum / version', __FILE__) Gem :: Specification.new do | gem | gem.authors = ["Claudio Ortolina"] gem.email = ["[email protected]"] gem.description =% q TODO: Write a gem description gem.summary =% q TODO: Write a gem summary  gem.homepage = "" gem.executables = 'git ls-files - bin / *'. split ("\ n"). map | f | File.basename (f) gem.files = 'git ls-files'.split ("\ n") gem.test_files =' git ls-files - test, spec, features / * '. Split (" \ n ") gem.name =" bramipsum "gem.require_paths = [" lib "] gem.version = Bramipsum :: VERSION gem.add_development_dependency 'rake' end

Vervolgens kunnen we rennen bundel om Rake te installeren. Omdat het als ontwikkelingsafhankelijkheid is toegevoegd, zal het niet door Bundler worden geïnstalleerd wanneer iemand onze edelsteen gebruikt.

Een paar interessante opmerkingen over het bestand:

  • Het bevat de Ruby 1.9 openingscommentaar die de bestandscodering specificeert. Dit is belangrijk, omdat sommige gegevens in het bestand (zoals de e-mail of de naam van de auteur) een niet-ascii-teken kunnen zijn.
  • Omschrijving en samenvatting moet worden gewijzigd om correct te worden weergegeven op Rubygems.
  • De versie is gedefinieerd binnen de lib / bramipsum / versie bestand, vereist bovenaan. Het definieert de VERSIE constant, genaamd vlak voor het einde van het bestand.

De lib-map

De lib map bevat een generiek bramipsum.rb bestand dat de versie module. Zelfs als de opmerking in het bestand suggereert dat je code rechtstreeks aan het bestand zelf toevoegt, zullen we het alleen gebruiken om de afzonderlijke klassen te vereisen die onze kleine edelsteen vormen.


De basisgegevens bijwerken en een testraamwerk toevoegen

Laten we beginnen met het bijwerken van de gegevens in bramipsum.gemspec:

... gem.description =% q Willekeurige zinnen van Bram Stoker's Dracula gem.summary =% q Genereer een of meer dummy zinnen uit Bram Stoker's Dracula ... 

Heel simpele dingen. Laten we vervolgens ondersteuning toevoegen voor de juiste tests. We zullen gebruiken minitest, zoals het standaard is opgenomen in Ruby 1.9. Laten we er een toevoegen test directory:

mkdir-test

Vervolgens hebben we een test_helper.rb bestand en een test voor de aanwezigheid van de Bramipsum :: VERSION constante.

aanraaktest / test_helper.rb mkdir-p test / lib / bramipsum aanraaktest / lib / bramipsum / version_test.rb

Laten we de. Openen test_helper.rb bestand en voeg een paar regels toe:

vereist 'minitest / autorun' vereist 'minitest / pride' vereist File.expand_path ('... / ... /lib/bramipsum.rb', __FILE__)

Het vereist zowel Minitest als Pride voor gekleurde uitvoer; dan heeft het het belangrijkste bramipsum-bestand nodig.

De version_test.rb bestand moet worden bijgewerkt met de volgende code:

require_relative '... / ... / test_helper' beschrijven Bramipsum doen 'moet worden gedefinieerd "do Bramipsum :: VERSION.wont_be_nil end end

We gebruiken het verwachtingsformaat voor onze tests. De test zelf is redelijk duidelijk en kan eenvoudig worden uitgevoerd door te typen:

ruby test / lib / bramipsum / version_test.rb

Je moet een slaagtest hebben!

Laten we nu het Rakefile om een ​​comfortabelere manier te hebben om onze tests uit te voeren. Wis alles en plak de volgende code:

#! / usr / bin / env rake vereisen "bundler / gem_tasks" vereisen 'rake / testtask' Rake :: TestTask.new do | t | t.libs << 'lib/bramipsum' t.test_files = FileList['test/lib/bramipsum/*_test.rb'] t.verbose = true end task :default => :test

Hierdoor kunnen we onze tests uitvoeren door te typen hark uit de gem root-map.


Functionaliteit toevoegen

Aangezien de focus van deze zelfstudie een juweel is, beperken we de hoeveelheid functionaliteit die we gaan toevoegen.


Basisklasse

Bramipsum is nog steeds een lege huls. Omdat we het boek van Dracula willen gebruiken om zinnen te genereren, is het tijd om het aan de repository toe te voegen. Ik heb een versie van het boek voorbereid waarin ik alle inhoud heb verwijderd, behalve het verhaal zelf: laten we het toevoegen aan het project.

mkdir -p boek krul https://raw.github.com/cloud8421/bundler-gem-tutorial/master/book/dracula.txt -o boek / dracula.txt

Laten we nu een maken Baseren klasse, waar alle methoden worden toegevoegd die nodig zijn om gegevens uit het boek te extraheren.

touch lib / bramipsum / base.rb touch test / lib / bramipsum / base_test.rb

Het testbestand zal slechts een paar verwachtingen hebben:

require_relative '... / ... / test_helper' beschrijven Bramipsum :: Base do subject Bramipsum :: Base beschrijven "lezen van bestand" doen het "moet een bron hebben" do subject.must_respond_to (: source) end it "must have the dracula bestand als een bron "do subject.source.must_be_instance_of (String) end end omschrijven" splitsing in regels "doet het" moet het bestand correct in regels worden verdeeld "do subject.processed_source.must_be_instance_of (Array) end it" moet correct lege regels verwijderen "do subject.processed_source.wont_include (nil) end end end

hardlopen hark nu zal een uitzondering verschijnen, zoals de base.rb bestand is nog steeds leeg. Baseren zal gewoon de inhoud van het bestand lezen en een reeks regels retourneren (de lege regels verwijderen).

De implementatie is heel eenvoudig:

module Bramipsum class Base def self.source @ source || = self.read end def self.processed_source @processed_source || = self.source.split ("\ n"). uniq end private def self.read File.read (Bestand .expand_path ('book / dracula.txt')) end end end

We definiëren een reeks klassemethoden die de oorspronkelijke tekst en een verwerkte versie bevatten, waarbij de resultaten na de eerste uitvoering in de cache worden opgeslagen.

We moeten dan openen lib / bramipsum.rb en voeg de juiste instructie toe:

require_relative "./bramipsum/base"

Als u opslaat en uitvoert hark nu zou je alle tests moeten zien passeren.


Zinklasse

Vervolgens moeten we een nieuwe klasse toevoegen om zinnen te genereren. We zullen het noemen Zin.

touch lib / bramipsum / zin.rb aanraaktest / lib / bramipsum / sentence_test.rb

Net als voorheen moeten we openen lib / bramipsum.rb en het nieuw gecreëerde bestand vereisen:

require_relative "./bramipsum/base" require_relative "./bramipsum/sentence"

Deze klasse ervaart van Baseren, zodat we de implementatie minimaal kunnen houden. De test heeft slechts drie verwachtingen nodig:

require_relative '... / ... / test_helper' beschrijven Bramipsum :: Zin do subject Bramipsum :: Sentence it "moet een willekeurige zin retourneren" do subject.sentence.must_be_instance_of (String) end it "moet standaard 5 zinnen retourneren" do subject .sentences.size.must_equal (5) einde "moet het opgegeven aantal zinnen retourneren" do subject.sentences (10) .size.must_equal (10) end end

Het idee is dat we kunnen bellen Bramipsum :: Sentence.sentence of Bramipsum :: Sentence.sentences (10) om te genereren wat we nodig hebben.

De inhoud voor sentence.rb is ook heel beknopt:

module Bramipsum klasse Zin < Base def self.sentence self.processed_source.sample end def self.sentences(n=5) self.processed_source.sample(n) end end end

Aangezien we Ruby 1.9 gebruiken, kunnen we de monster methode om een ​​willekeurig element uit een array te retourneren.

Nogmaals, hardlopen hark zou alle tests moeten laten zien die voorbijgaan.


Het bouwen en distribueren van de edelsteen

Als je rent edelsteen bouwen vanaf de opdrachtregel wordt een lokale kopie van het juweel gebouwd en voor u verpakt. Als u het niet hoeft te verspreiden of als u het privé moet houden, kunt u hier stoppen. Maar als het een project is dat open-source kan zijn, moedig ik je aan om dat te doen.

De voor de hand liggende stap is om onze gloednieuwe edelsteen toe te voegen aan RubyGems.org.

Nadat u een account op de site hebt gemaakt, bezoekt u uw profiel. U zult een commando vinden dat u moet uitvoeren om uw computer te autoriseren. In mijn geval was het:

curl -u cloud8421 https://rubygems.org/api/v1/api_key.yaml> ~ / .gem / referenties

Je bent nu slechts één stap verwijderd om het juweel op Rubygems te publiceren, maar doe het niet tenzij je het echt wilt. Het commando dat je zou uitvoeren is:

gem push bramipsum-0.0.1.gem

Conclusie

Gefeliciteerd! U weet nu hoe u een juweel vanuit het niets kunt maken met behulp van Bundler. Er zijn echter nog andere dingen om rekening mee te houden:

  • Compatibiliteit: misschien wilt u Ruby 1.8 ook ondersteunen. Dat vereist het refactoren van alle require_relative gesprekken; daarnaast moet je de minitest edelsteen, omdat deze standaard niet is opgenomen in Ruby 1.8
  • Continue integratie: je kunt ondersteuning toevoegen aan Travis CI en je edelsteen zal worden getest in de cloud tegen alle belangrijke Ruby-releases. Dit maakt het eenvoudig om er zeker van te zijn dat er geen problemen zijn met platform-specifieke gedragsveranderingen.
  • Documentatie: dit is belangrijk, het is goed om RDoc-opmerkingen te hebben die kunnen helpen bij het genereren van automatische documenten en een goed README-bestand met voorbeelden en richtlijnen.

Bedankt voor het lezen! Nog vragen?