Création d'un Gem Ruby Complet pour la Conversion de Casse de Chaînes
Ce quide vous accompagnera à travers la création d'un gem Ruby nommé string_case_converter
qui ajoutera des méthodes de conversion camelCase
, snake_case
, PascalCase
et "regular" (espace-séparé, première lettre majuscule) à la classe String
. Nous couvrirons tous les aspects d'un gem professionnel : tests, Rake, YARD (avec @example
), RuboCop, gem_release
, statistiques de code (avec code_statistics
), vérifications CVE avec Brakeman et Bundle Audit, ainsi que l'intégration continue (CI) avec GitHub Actions et l'analyse de code avec Code Climate.
Objectif du Gem
Le gem string_case_converter
étendra la classe String
de Ruby pour ajouter les méthodes suivantes :
to_camel_case
: Convertit une chaîne encamelCase
.to_snake_case
: Convertit une chaîne ensnake_case
.to_pascal_case
: Convertit une chaîne enPascalCase
.to_regular_case
: Convertit une chaîne en une forme "régulière" (espace-séparée, première lettre majuscule).
Prérequis
Avant de commencer, assurez-vous d'avoir les éléments suivants installés :
- Ruby (version 2.7 ou supérieure recommandée)
- Bundler (
gem install bundler
) - Git (pour la gestion de version et
gem_release
) - Bundle Audit (
gem install bundle-audit
) - Un compte GitHub (pour l'intégration continue et l'hébergement du code).
- Un compte Code Climate (optionnel, pour les badges de maintenabilité et de couverture).
Étape 1 : Initialisation du Gem avec Bundler
Remarque : pour réaliser une création jusqu'au bout, vous dever choisir un autre nom de gem et le faire avec du code que vous voulez réellement publier ( ne polluer pas Rubygems avec un gem fictif.
Bundler est l'outil standard pour créer la structure de base d'un gem.
Créez le squelette du gem :
bundle gem string_case_converter --test=rspec --rubocop --no-exe
- --test=rspec: Configure RSpec comme framework de test.
- --rubocop: Ajoute RuboCop pour le linting.
- --no-exe: Nous n'avons pas besoin d'un exécutable binaire pour ce gem simple.
Naviguez dans le répertoire du gem
cd string_case_converter
- Mettez à jour les dépendances de développement et les informations du gem dans string_case_converter.gemspec
- Ouvrez le fichier string_case_converter.gemspec.
# emacs string_case_converter.gemspec
- Ajoutez les dépendances suivantes dans la section spec.add_development_dependency:
# ...
spec.add_development_dependency "rspec", "~> 3.0" spec.add_development_dependency "rubocop", "~> 1.0" spec.add_development_dependency "yard", "~> 0.9" # Pour la documentation spec.add_development_dependency "simplecov", "~> 0.18" # Pour la couverture de code spec.add_development_dependency "simplecov-lcov", "~> 0.3" # Pour générer des rapports LCOV pour Code Climate spec.add_development_dependency "brakeman", "~> 5.0" # Pour l'analyse de sécurité du code spec.add_development_dependency "bundle-audit", "~> 0.9" # Pour l'analyse de sécurité des dépendances spec.add_development_dependency "code_statistics", "~> 0.1" # Pour les statistiques de lignes de code spec.add_development_dependency "gem_release", "~> 2.0" # Pour la gestion des versions # ...
- Mettez à jour les informations du gem pour inclure la licence et les liens vers le dépôt (remplacez votre_utilisateur_github et votre_repo_github par vos informations réelles si vous comptez le publier) :
# ...
spec.homepage = "https://github.com/votre_utilisateur_github/string_case_converter"
spec.license = "MIT" # Spécifie la licence
spec.metadata["allowed_push_host"] = "https://rubygems.org" # Recommandé pour la publication
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md" # Optionnel, mais bonne pratique
# ...
- Installez les dépendances :
bundle install
Étape 2 : Ajout du README et de la Licence MIT
Un fichier README.md
fournit des informations essentielles sur votre gem, et un fichier LICENSE.txt
spécifie les conditions d'utilisation.
Créez le fichier LICENSE.txt
Dans le répertoire racine de votre gem (string_case_converter/
), créez un fichier nommé LICENSE.txt
et ajoutez le contenu suivant (remplacez [YEAR]
et [COPYRIGHT HOLDER NAME]
par les informations appropriées) :
MIT License
Copyright (c) [YEAR] [COPYRIGHT HOLDER NAME]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Créez le fichier README.md
Dans le répertoire racine de votre gem (string_case_converter/
), créez un fichier nommé README.md
et ajoutez le contenu suivant. Nous inclurons des badges qui seront mis à jour automatiquement par GitHub Actions et Code Climate.
# String Case Converter
[](https://badge.fury.io/rb/string_case_converter)
[](https://github.com/votre_utilisateur_github/string_case_converter/actions/workflows/ruby.yml)
[](https://codeclimate.com/github/votre_utilisateur_github/string_case_converter/maintainability)
[](https://codeclimate.com/github/votre_utilisateur_github/string_case_converter/test_coverage)
[](https://www.rubydoc.info/gems/string_case_converter)
Un gem Ruby léger qui étend la classe `String` pour ajouter des méthodes de conversion de casse (camelCase, snake_case, PascalCase, et regular case).
## Installation
Ajoutez cette ligne à votre `Gemfile` :
gem 'string_case_converter'
Puis exécutez :
bundle install
Ou installez-le directement :
gem install string_case_converter
## Utilisation
Le gem utilise les https://docs.ruby-lang.org/en/master/doc/syntax/refinements_rdoc.html de Ruby pour étendre la classe String. Vous devez donc using StringCaseConverter dans le scope où vous souhaitez utiliser les méthodes.
require 'string_case_converter'
# Active les refinements pour le scope actuel
using StringCaseConverter
# Conversion en snake_case
puts "CamelCaseString".to_snake_case #=> "camel_case_string"
puts "PascalCaseString".to_snake_case #=> "pascal_case_string"
puts "kebab-case-string".to_snake_case #=> "kebab_case_string"
puts "Regular Case String".to_snake_case #=> "regular_case_string"
puts "HTTPResponse".to_snake_case #=> "http_response"
# Conversion en camelCase
puts "snake_case_string".to_camel_case #=> "snakeCaseString"
puts "PascalCaseString".to_camel_case #=> "pascalCaseString"
puts "kebab-case-string".to_camel_case #=> "kebabCaseString"
puts "Regular Case String".to_camel_case #=> "regularCaseString"
puts "http_response".to_camel_case #=> "httpResponse"
# Conversion en PascalCase
puts "snake_case_string".to_pascal_case #=> "SnakeCaseString"
puts "camelCaseString".to_pascal_case #=> "CamelCaseString"
puts "kebab-case-string".to_pascal_case #=> "KebabCaseString"
puts "Regular Case String".to_pascal_case #=> "RegularCaseString"
puts "http_response".to_pascal_case #=> "HttpResponse"
# Conversion en regular case (espace-séparé, première lettre majuscule)
puts "snake_case_string".to_regular_case #=> "Snake case string"
puts "camelCaseString".to_regular_case #=> "Camel case string"
puts "PascalCaseString".to_regular_case #=> "Pascal case string"
puts "kebab-case-string".to_regular_case #=> "Kebab case string"
puts "HTTPResponse".to_regular_case #=> "Http response"
## Développement
Après avoir cloné le dépôt, exécutez bundle install pour installer les dépendances. Ensuite, exécutez bundle exec rake spec pour lancer les tests.
Vous pouvez également exécuter bin/console pour un shell interactif qui vous permettra d'expérimenter.
Pour installer ce gem sur votre machine locale, exécutez bundle exec rake install. Pour publier une nouvelle version, mettez à jour le numéro de version dans version.rb, puis exécutez bundle exec rake release, qui créera un tag Git pour la version, poussera les commits et le tag, et poussera le fichier .gem vers https://rubygems.org.
Tâches Rake Utiles
bundle exec rake spec: Exécute les tests RSpec.
bundle exec rake rubocop: Exécute RuboCop pour le linting du code (avec auto-correction).
bundle exec rake yard: Génère la documentation YARD.
bundle exec rake coverage: Exécute les tests avec un rapport de couverture de code.
bundle exec rake stats: Affiche les statistiques de lignes de code (fourni par code_statistics).
bundle exec rake brakeman: Scanne le code pour les vulnérabilités de sécurité.
bundle exec rake audit: Scanne les dépendances pour les vulnérabilités connues.
bundle exec rake security_check: Exécute brakeman et audit.
## Contribution
Les rapports de bugs et les pull requests sont les bienvenus sur GitHub à l'adresse https://github.com/votre_utilisateur_github/string_case_converter.
Licence
Le gem est disponible en tant qu'open source sous les termes de la https://opensource.org/licenses/MIT.
Note : Remplacezvotre_utilisateur_github
etvotre_repo_github
par vos informations réelles. LesYOUR_CODECLIMATE_..._ID
seront remplacés à l'étape 10.
Étape 3 : Implémentation de la logique principale
Nous allons utiliser les refinements de Ruby pour ajouter nos méthodes à la classeString
. C'est une approche plus propre que de modifier directementString
, car les méthodes ne seront disponibles que là où le module est explicitementusing
.
Mettez à jour lib/string_case_converter/version.rb
(si vous le souhaitez, mais gem_release
le gérera).
# lib/string_case_converter/version.rb
module StringCaseConverter
VERSION = "0.1.0"
end
Ouvrez lib/string_case_converter.rb
Et remplacez son contenu par ce qui suit. Notez l'utilisation des tags @example
pour les exemples de code.
# lib/string_case_converter.rb
module StringCaseConverter
# Refinements pour ajouter des méthodes de conversion de casse à la classe String.
refine String do
# Convertit une chaîne en snake_case.
#
# @return [String] La chaîne convertie en snake_case.
#
# @example Convertit une chaîne camelCase en snake_case
# "camelCaseString".to_snake_case #=> "camel_case_string"
# @example Convertit une chaîne PascalCase en snake_case
# "PascalCaseString".to_snake_case #=> "pascal_case_string"
# @example Convertit une chaîne kebab-case en snake_case
# "kebab-case-string".to_snake_case #=> "kebab_case_string"
# @example Convertit une chaîne avec des espaces en snake_case
# "Regular Case String".to_snake_case #=> "regular_case_string"
# @example Gère les acronymes (ex: HTTPResponse)
# "HTTPResponse".to_snake_case #=> "http_response"
# @example Gère les acronymes (ex: MyAPIKey)
# "MyAPIKey".to_snake_case #=> "my_api_key"
# @example Une chaîne déjà en snake_case reste inchangée
# "already_snake_case".to_snake_case #=> "already_snake_case"
# @example Gère une chaîne vide
# "".to_snake_case #=> ""
def to_snake_case
self
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') # Gère les acronymes (ex: HTTPResponse -> HTTP_Response)
.gsub(/([a-z\d])([A-Z])/, '\1_\2') # Gère les transitions minuscules/majuscules (ex: fooBar -> foo_Bar)
.tr("-", "_") # Convertit les tirets en underscores (kebab-case)
.gsub(/\s/, '_') # Convertit les espaces en underscores
.downcase # Met tout en minuscules
end
# Convertit une chaîne en camelCase.
#
# @return [String] La chaîne convertie en camelCase.
#
# @example Convertit une chaîne snake_case en camelCase
# "snake_case_string".to_camel_case #=> "snakeCaseString"
# @example Convertit une chaîne PascalCase en camelCase
# "PascalCaseString".to_camel_case #=> "pascalCaseString"
# @example Convertit une chaîne kebab-case en camelCase
# "kebab-case-string".to_camel_case #=> "kebabCaseString"
# @example Convertit une chaîne avec des espaces en camelCase
# "Regular Case String".to_camel_case #=> "regularCaseString"
# @example Gère les acronymes (ex: HTTP_Response)
# "http_response".to_camel_case #=> "httpResponse"
# @example Gère les acronymes (ex: my_api_key)
# "my_api_key".to_camel_case #=> "myApiKey"
# @example Une chaîne déjà en camelCase reste inchangée
# "alreadyCamelCase".to_camel_case #=> "alreadyCamelCase"
# @example Gère une chaîne vide
# "".to_camel_case #=> ""
def to_camel_case
self
.to_snake_case # Commence par convertir en snake_case pour une base cohérente
.gsub(/_([a-z])/) { Regexp.last_match(1).upcase } # Met en majuscule la lettre après un underscore
.sub(/^[a-z]/) { |match| match.downcase } # S'assure que la première lettre est en minuscule (camelCase)
end
# Convertit une chaîne en PascalCase (première lettre de chaque mot en majuscule).
#
# @return [String] La chaîne convertie en PascalCase.
#
# @example Convertit une chaîne snake_case en PascalCase
# "snake_case_string".to_pascal_case #=> "SnakeCaseString"
# @example Convertit une chaîne camelCase en PascalCase
# "camelCaseString".to_pascal_case #=> "CamelCaseString"
# @example Convertit une chaîne kebab-case en PascalCase
# "kebab-case-string".to_pascal_case #=> "KebabCaseString"
# @example Convertit une chaîne avec des espaces en PascalCase
# "Regular Case String".to_pascal_case #=> "RegularCaseString"
# @example Gère les acronymes (ex: http_response)
# "http_response".to_pascal_case #=> "HttpResponse"
# @example Gère les acronymes (ex: my_api_key)
# "my_api_key".to_pascal_case #=> "MyApiKey"
# @example Une chaîne déjà en PascalCase reste inchangée
# "AlreadyPascalCase".to_pascal_case #=> "AlreadyPascalCase"
# @example Gère une chaîne vide
# "".to_pascal_case #=> ""
def to_pascal_case
self
.to_snake_case # Commence par convertir en snake_case
.gsub(/_([a-z])/) { Regexp.last_match(1).upcase } # Met en majuscule la lettre après un underscore
.sub(/^[a-z]/) { |match| match.upcase } # S'assure que la première lettre est en majuscule (PascalCase)
end
# Convertit une chaîne en une forme "régulière" (mots séparés par des espaces, première lettre majuscule).
#
# @return [String] La chaîne convertie en forme régulière.
#
# @example Convertit une chaîne snake_case en forme régulière
# "snake_case_string".to_regular_case #=> "Snake case string"
# @example Convertit une chaîne camelCase en forme régulière
# "camelCaseString".to_regular_case #=> "Camel case string"
# @example Convertit une chaîne PascalCase en forme régulière
# "PascalCaseString".to_regular_case #=> "Pascal case string"
# @example Convertit une chaîne kebab-case en forme régulière
# "kebab-case-string".to_regular_case #=> "Kebab case string"
# @example Gère les acronymes (ex: HTTPResponse)
# "HTTPResponse".to_regular_case #=> "Http response"
# @example Gère les acronymes (ex: MyAPIKey)
# "MyAPIKey".to_regular_case #=> "My api key"
# @example Une chaîne déjà en forme régulière reste inchangée (si capitalisée)
# "Regular case string".to_regular_case #=> "Regular case string"
# @example Gère une chaîne vide
# "".to_regular_case #=> ""
def to_regular_case
self
.to_snake_case # Commence par convertir en snake_case
.gsub('_', ' ') # Remplace les underscores par des espaces
.capitalize # Met la première lettre de la phrase en majuscule
end
end
end
Étape 4 : Écriture des Tests avec RSpec
Les tests sont cruciaux pour s'assurer que votre code fonctionne comme prévu et pour prévenir les régressions.
Ouvrez spec/string_case_converter_spec.rb
Et remplacez son contenu par :
# spec/string_case_converter_spec.rb
require "string_case_converter"
# Active les refinements pour les tests
using StringCaseConverter
RSpec.describe StringCaseConverter do
describe String do
context "#to_snake_case" do
it "converts camelCase to snake_case" do
expect("camelCaseString".to_snake_case).to eq("camel_case_string")
end
it "converts PascalCase to snake_case" do
expect("PascalCaseString".to_snake_case).to eq("pascal_case_string")
end
it "converts kebab-case to snake_case" do
expect("kebab-case-string".to_snake_case).to eq("kebab_case_string")
end
it "converts regular case to snake_case" do
expect("Regular Case String".to_snake_case).to eq("regular_case_string")
end
it "handles acronyms correctly" do
expect("HTTPResponse".to_snake_case).to eq("http_response")
expect("MyAPIKey".to_snake_case).to eq("my_api_key")
end
it "returns snake_case string as is" do
expect("already_snake_case".to_snake_case).to eq("already_snake_case")
end
it "handles empty string" do
expect("".to_snake_case).to eq("")
end
end
context "#to_camel_case" do
it "converts snake_case to camelCase" do
expect("snake_case_string".to_camel_case).to eq("snakeCaseString")
end
it "converts PascalCase to camelCase" do
expect("PascalCaseString".to_camel_case).to eq("pascalCaseString")
end
it "converts kebab-case to camelCase" do
expect("kebab-case-string".to_camel_case).to eq("kebabCaseString")
end
it "converts regular case to camelCase" do
expect("Regular Case String".to_camel_case).to eq("regularCaseString")
end
it "handles acronyms correctly" do
expect("http_response".to_camel_case).to eq("httpResponse")
expect("my_api_key".to_camel_case).to eq("myApiKey")
end
it "returns camelCase string as is" do
expect("alreadyCamelCase".to_camel_case).to eq("alreadyCamelCase")
end
it "handles empty string" do
expect("".to_camel_case).to eq("")
end
end
context "#to_pascal_case" do
it "converts snake_case to PascalCase" do
expect("snake_case_string".to_pascal_case).to eq("SnakeCaseString")
end
it "converts camelCase to PascalCase" do
expect("camelCaseString".to_pascal_case).to eq("CamelCaseString")
end
it "converts kebab-case to PascalCase" do
expect("kebab-case-string".to_pascal_case).to eq("KebabCaseString")
end
it "converts regular case to PascalCase" do
expect("Regular Case String".to_pascal_case).to eq("RegularCaseString")
end
it "handles acronyms correctly" do
expect("http_response".to_pascal_case).to eq("HttpResponse")
expect("my_api_key".to_pascal_case).to eq("MyApiKey")
end
it "returns PascalCase string as is" do
expect("AlreadyPascalCase".to_pascal_case).to eq("AlreadyPascalCase")
end
it "handles empty string" do
expect("".to_pascal_case).to eq("")
end
end
context "#to_regular_case" do
it "converts snake_case to regular case" do
expect("snake_case_string".to_regular_case).to eq("Snake case string")
end
it "converts camelCase to regular case" do
expect("camelCaseString".to_regular_case).to eq("Camel case string")
end
it "converts PascalCase to regular case" do
expect("PascalCaseString".to_regular_case).to eq("Pascal case string")
end
it "converts kebab-case to regular case" do
expect("kebab-case-string".to_regular_case).to eq("Kebab case string")
end
it "handles acronyms correctly" do
expect("HTTPResponse".to_regular_case).to eq("Http response")
expect("MyAPIKey".to_regular_case).to eq("My api key")
end
it "returns regular case string as is (if already capitalized)" do
expect("Regular case string".to_regular_case).to eq("Regular case string")
end
it "handles empty string" do
expect("".to_regular_case).to eq("")
end
end
end
end
Exécutez les tests
bundle exec rspec
Tous les tests devraient passer.
Étape 5 : Configuration de Rakefile pour les Tâches
Le Rakefile
est le cœur de la gestion de votre gem. Il permet d'automatiser les tâches courantes.
Ouvrez Rakefile
Et ajoutez les lignes suivantes :
# Rakefile
require "bundler/gem_tasks"
require "rspec/core/rake_task"
require "rubocop/rake_task"
require "yard/rake/yardoc_task"
require "simplecov" # Pour la couverture de code
require "simplecov-lcov" # Pour générer des rapports LCOV
require "brakeman" # Pour l'analyse de sécurité du code
require "bundler/audit/task" # Pour l'analyse de sécurité des dépendances
require "code_statistics/rake_task" # Pour les statistiques de lignes de code
# Tâche RSpec
RSpec::Core::RakeTask.new(:spec)
# Tâche RuboCop
RuboCop::RakeTask.new(:rubocop) do |task|
task.options = ["--auto-correct-all"] # Optionnel: corrige automatiquement les problèmes
end
# Tâche YARD pour la documentation
YARD::Rake::YardocTask.new
# La tâche 'stats' est automatiquement ajoutée par 'code_statistics/rake_task'
# Elle affichera des statistiques détaillées sur le code.
# Tâche pour la couverture de code (nécessite l'exécution des tests)
desc "Exécute les tests avec couverture de code et génère un rapport LCOV"
task :coverage do
# SimpleCov est démarré dans spec/spec_helper.rb
# Nous configurons SimpleCov pour générer un rapport LCOV
SimpleCov::Formatter::LcovFormatter.config do |c|
c.report_with_single_file = true
c.single_report_path = 'coverage/lcov.info'
end
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
SimpleCov.start do
add_filter "/spec/"
add_filter "/vendor/"
end
Rake::Task["spec"].invoke
puts "Rapport de couverture généré dans ./coverage/index.html et ./coverage/lcov.info"
end
# Tâche pour la vérification des CVE avec Brakeman (code de l'application)
desc "Exécute Brakeman pour vérifier les vulnérabilités dans le code de l'application"
task :brakeman do
# Brakeman est principalement pour les applications Rails, mais peut trouver des problèmes génériques.
# Utiliser --no-exit-on-error pour ne pas échouer la tâche Rake si des avertissements sont trouvés.
sh "bundle exec brakeman -q -w1 -o brakeman_report.html --no-exit-on-error ."
puts "Rapport Brakeman généré dans brakeman_report.html"
end
# Tâche pour la vérification des CVE avec Bundle Audit (dépendances)
desc "Exécute bundle audit pour vérifier les vulnérabilités des dépendances"
task :audit do
sh "bundle audit check --update" # --update pour s'assurer que la base de données des advisories est à jour
end
# Tâche pour exécuter toutes les vérifications de sécurité
desc "Exécute toutes les vérifications de sécurité (brakeman et bundle audit)"
task :security_check => [:brakeman, :audit]
# Tâche par défaut (exécute les tests et rubocop)
task default: %i[rubocop spec]
Vérifiez les tâches disponibles
$ bundle exec rake -T
Vous devriez voir toutes les tâches que nous avons définies, y comprisrake audit
,rake security_check
etrake stats
(fournie parcode_statistics
).
Étape 6 : Linting du Code avec RuboCop
RuboCop est un linter et un formateur de code Ruby. Il aide à maintenir un style de code cohérent.
Exécutez RuboCop
bundle exec rubocop
Si des problèmes sont trouvés, vous pouvez les corriger manuellement ou utiliser :
bundle exec rubocop --auto-correct-all
Ou simplement bundle exec rake rubocop
comme vous avez configuré l'option --auto-correct-all
dans le Rakefile à l'étape 5
Personnalisation de RuboCop
Le fichier .rubocop.yml
a été créé par Bundler. Vous pouvez le modifier pour adapter les règles à vos préférences. Par exemple, pour ignorer certains fichiers ou désactiver certaines règles.
Étape 7 : Documentation avec YARD
YARD est un générateur de documentation pour Ruby. Il utilise des commentaires spéciaux dans votre code (y compris les tags @example
) pour générer une documentation HTML.
Remarque : Les commentaires YARD ont déjà été ajoutés danslib/string_case_converter.rb
à l'étape 3, incluant les descriptions,@param
,@return
et surtout les@example
.
Visualisez la documentation
bundle exec yard server --reload
Ouvrez votre navigateur à l'adresse http://localhost:8808
pour voir la documentation. Vous pourrez naviguer vers les méthodes et voir les exemples de code formatés et mis en évidence.
Générez la documentation
bundle exec rake yard
Cela créera un répertoire doc/
contenant la documentation HTML.
Étape 8 : Statistiques du Code (LOC et Couverture)
Lignes de Code (LOC) avec code_statistics
Le gem code_statistics
fournit des statistiques détaillées sur votre code Ruby, y compris les lignes de code, les classes, les méthodes, etc.
Exécutez la tâche :
bundle exec rake stats
Cela affichera un tableau récapitulatif des statistiques de votre code.
Remarque : l'outil code_statistics est déjà configuré dans votre Rakefile à l'etape 5
Couverture de Code avec SimpleCov
SimpleCov est un outil de couverture de code. Il vous indique quelle partie de votre code est couverte par vos tests.
Configurez SimpleCov
Ouvrez spec/spec_helper.rb
et ajoutez les lignes suivantes tout en haut du fichier :
# spec/spec_helper.rb
require "simplecov"
require "simplecov-lcov" # Ajouté pour les rapports LCOV
# Configure SimpleCov pour générer un rapport LCOV pour les services CI
SimpleCov::Formatter::LcovFormatter.config do |c|
c.report_with_single_file = true
c.single_report_path = 'coverage/lcov.info'
end
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::LcovFormatter
])
SimpleCov.start do
add_filter "/spec/" # Exclut le répertoire des tests du rapport de couverture
add_filter "/vendor/" # Exclut les dépendances
end
require "bundler/setup"
require "string_case_converter"
RSpec.configure do |config|
# ... (reste de la configuration RSpec)
end
Exécutez la tâche de couverture
bundle exec rake coverage
Cela exécutera vos tests et générera un rapport de couverture dans le répertoire coverage/
. Ouvrez coverage/index.html
dans votre navigateur pour voir le rapport détaillé. Un fichier coverage/lcov.info
sera également généré, utile pour les services CI.
Remarque : l'outil SimpleCov est déjà initialisé dans votre Rakefile à l'etape 5
Étape 9 : Intégration Continue (CI) avec GitHub Actions
L'intégration continue est cruciale pour automatiser les tests, le linting et les vérifications de sécurité à chaque push ou pull request.
Initialisez un dépôt Git et poussez-le sur GitHub
Si cela n'a pas déjçà été fait
git init
git add .
git commit -m "Initial commit of string_case_converter gem with basic structure"
# Créez un dépôt sur GitHub et ajoutez-le comme remote
git remote add origin https://github.com/votre_utilisateur_github/string_case_converter.git
git push -u origin main # Ou master, selon votre branche par défaut
Créez le fichier de workflow GitHub Actions
Dans le répertoire racine de votre gem, créez le dossier .github/workflows/
et à l'intérieur, un fichier nommé ruby.yml
:
mkdir -p .github/workflows
touch .github/workflows/ruby.yml
Ajoutez le contenu suivant à .github/workflows/ruby.yml
# .github/workflows/ruby.yml
name: Ruby CI
on:
push:
branches: [ "main", "master" ]
pull_request:
branches: [ "main", "master" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['2.7', '3.0', '3.1', '3.2'] # Testez sur différentes versions de Ruby
steps:
- uses: actions/checkout@v3 # Récupère le code du dépôt
- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # Installe les dépendances avec Bundler
- name: Run RuboCop
run: bundle exec rake rubocop
- name: Run RSpec tests with coverage
run: bundle exec rake coverage # Exécute les tests et génère le rapport LCOV
- name: Run Brakeman security scan
run: bundle exec rake brakeman
- name: Run Bundle Audit security scan
run: bundle exec rake audit
# Étape optionnelle pour uploader la couverture de code vers Code Climate
# Nécessite la configuration de Code Climate à l'étape suivante
- name: Upload coverage to Code Climate
if: success() # N'exécute que si les étapes précédentes ont réussi
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} # Variable d'environnement secrète
run: |
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
chmod +x ./cc-test-reporter
./cc-test-reporter format-coverage -t lcov -o coverage/codeclimate.json coverage/lcov.info
./cc-test-reporter upload-coverage -i coverage/codeclimate.json
Commitez et poussez le workflow
git add .github/workflows/ruby.yml
git commit -m "Add GitHub Actions CI workflow"
git push
Rendez-vous sur l'onglet "Actions" de votre dépôt GitHub pour voir le workflow s'exécuter.
Étape 10 : Services d'Analyse de Code (Code Climate)
Remarque : L'usage de Code Climate n'est pas obligatoire et cela vous demande un compte, si vous voulez l'eviter, vous devrez supprimer les badges du README.md correspondants.
Code Climate fournit des métriques de maintenabilité et de couverture de code, et les affiche sous forme de badges.
- Inscrivez-vous sur Code Climate :
Rendez-vous sur codeclimate.com et connectez-vous avec votre compte GitHub. Ajoutez votre dépôtstring_case_converter
. - Récupérez les IDs des badges :
Une fois votre dépôt ajouté, Code Climate vous fournira des IDs pour la maintenabilité et la couverture.- Pour la maintenabilité, vous trouverez un badge avec un ID comme
YOUR_CODECLIMATE_MAINTAINABILITY_ID
. - Pour la couverture, vous devrez peut-être configurer l'upload (voir l'étape suivante), mais l'ID sera similaire :
YOUR_CODECLIMATE_COVERAGE_ID
.
- Pour la maintenabilité, vous trouverez un badge avec un ID comme
- Mettez à jour le
README.md
:
Remplacez les placeholdersYOUR_CODECLIMATE_MAINTAINABILITY_ID
etYOUR_CODECLIMATE_COVERAGE_ID
dans votreREADME.md
avec les IDs réels fournis par Code Climate. - Configurez la variable d'environnement
CC_TEST_REPORTER_ID
sur GitHub :
Pour que GitHub Actions puisse uploader les rapports de couverture à Code Climate, vous devez stocker votreCC_TEST_REPORTER_ID
(fourni par Code Climate après avoir ajouté votre repo) comme secret GitHub.Maintenant, chaque fois que votre workflow GitHub Actions s'exécutera, il enverra les données de couverture à Code Climate, et vos badges se mettront à jour.- Dans votre dépôt GitHub, allez dans
Settings
>Secrets and variables
>Actions
>New repository secret
. - Nommez le secret
CC_TEST_REPORTER_ID
. - Collez la valeur de votre
CC_TEST_REPORTER_ID
(obtenue depuis Code Climate) dans le champ "Secret". - Cliquez sur "Add secret".
- Dans votre dépôt GitHub, allez dans
Étape 11 : Gestion des Versions avec gem_release
gem_release
simplifie le processus de versioning, de taggage Git et de publication de votre gem.
Utilisation de gem_release
: gem_release
ajoute des tâches Rake pour gérer les versions.
Mettre à jour une version patch (0.1.0 -> 0.1.1)
bundle exec rake release:patch
Mettre à jour une version mineure (0.1.0 -> 0.2.0)
bundle exec rake release:minor
Mettre à jour une version majeure (0.1.0 -> 1.0.0)
bundle exec rake release:major
Principe
Chacune de ces commandes :
- Met à jour le numéro de version dans
lib/string_case_converter/version.rb
. - Crée un commit Git pour le changement de version.
- Crée un tag Git (ex:
v0.1.1
). - Pousse le commit et le tag vers votre dépôt distant (si configuré).
- Construit le gem (
.gem
file). - Publie le gem sur RubyGems.org (si vous êtes connecté et autorisé).
Important : Pour publier sur RubyGems.org, vous devez avoir un compte et être connecté viagem push
. Pour un premier test, vous pouvez simplement utiliserrake release:patch
et annuler la publication si vous ne voulez pas le rendre public tout de suite.
Étape 12 : Vérification des Vulnérabilités (CVE) avec Brakeman et Bundle Audit
Ces deux outils sont complémentaires pour la sécurité de votre projet Ruby.
Vérification du Code de l'Application avec Brakeman
Brakeman est un scanner de vulnérabilités statique pour les applications Ruby on Rails. Bien qu'il soit principalement conçu pour Rails, il peut détecter certaines vulnérabilités génériques dans le code Ruby.
- Interprétation :
Pour un gem comme celui-ci, qui ne gère pas d'entrées utilisateur complexes, de bases de données ou de sessions, Brakeman trouvera probablement peu ou pas de vulnérabilités. C'est normal. L'objectif est de montrer comment l'intégrer.
Exécutez Brakeman :
bundle exec rake brakeman
Cela exécutera Brakeman et générera un rapport HTML (brakeman_report.html
) dans le répertoire racine de votre gem.
Vérification des Dépendances avec Bundle Audit
bundle audit
scanne votre fichier Gemfile.lock
pour identifier les dépendances qui contiennent des vulnérabilités connues, en se basant sur la base de données Ruby Advisory Database.
- Interprétation :
- Si aucune vulnérabilité n'est trouvée, vous verrez un message comme "No vulnerabilities found".
- Si des vulnérabilités sont détectées,
bundle audit
listera les gems concernées, la version vulnérable, la version corrigée (si disponible) et un lien vers l'advisory de sécurité. Il est crucial de mettre à jour ces dépendances dès que possible.
Exécutez Bundle Audit :
bundle exec rake audit
La première fois, il téléchargera la base de données des advisories. Ensuite, il vérifiera vos dépendances.
Exécuter toutes les vérifications de sécurité
Vous pouvez exécuter les deux outils en une seule commande :
bundle exec rake security_check
Cette tâche est également exécutée automatiquement par votre workflow GitHub Actions.
Étape 13 : Construction et Publication du Gem
Bien que gem_release
gère la publication, il est bon de connaître les commandes manuelles.
Publier le gem sur RubyGems.org
Assurez-vous d'avoir un compte RubyGems.org et d'être connecté (gem push
).
bundle exec rake release
Cette commande (fournie par gem_release
) construira, taggera, poussera et publiera votre gem.
Installer le gem localement
bundle exec rake install
Cela installera le gem sur votre système local, vous permettant de le require
dans d'autres projets sans le publier.
Construire le gem
bundle exec rake build
Cela créera le fichier .gem
(ex: string_case_converter-0.1.0.gem
) dans le répertoire pkg/
.
Conclusion
Félicitations ! Vous avez créé un gem Ruby complet et professionnel, intégrant toutes les bonnes pratiques modernes :
- Fonctionnalités de conversion de casse robustes.
- Tests unitaires avec RSpec.
- Documentation claire avec YARD et des exemples intégrés.
- Linting du code avec RuboCop.
- Statistiques de code (LOC et couverture) avec
code_statistics
et SimpleCov. - Intégration Continue avec GitHub Actions pour automatiser les vérifications.
- Analyse de code avec Code Climate pour la maintenabilité et la couverture.
- Gestion des versions simplifiée avec
gem_release
. - Vérifications de sécurité approfondies avec Brakeman (code) et Bundle Audit (dépendances).
- Un README.md informatif et une licence MIT claire.
Ce didacticiel vous fourni une base solide pour développer, maintenir et distribuer des gems Ruby de haute qualité et sécurisés.