101 votes

Existe-t-il un moyen de créer un alias/ancre pour un tableau en YAML ?

Je suis en train d'utiliser Jammit pour regrouper les ressources d'une application Rails et j'ai quelques fichiers de ressources que je souhaite inclure dans quelques groupes. Par exemple, je voudrais que Sammy et ses plugins soient présents à la fois dans mes packages JS mobile et screen.

J'ai essayé ceci :

sammy: &SAMMY
  - public/javascripts/vendor/sammy.js
  - public/javascripts/vendor/sammy*.js

mobile:
  <<: *SAMMY
  - public/javascripts/something_else.js

et ceci :

mobile:
  - *SAMMY

mais les deux placent les fichiers JS de Sammy dans un tableau imbriqué, que Jammit ne peut pas comprendre. Existe-t-il une syntaxe pour inclure directement les éléments d'un tableau dans un autre tableau ?

NB : Je réalise que dans ce cas il n'y a que deux éléments dans le tableau SAMMY, donc ce ne serait pas trop difficile de donner un alias à chacun et de les référencer tous les deux dans chaque package. C'est bien pour ce cas, mais cela devient rapidement ingérable lorsqu'il y a cinq ou dix éléments qui ont un ordre de chargement spécifique.

77voto

yngve Points 371

La solution la plus proche que je connaisse est la suivante:

sammy:
  - &SAMMY1
    public/javascripts/vendor/sammy.js
  - &SAMMY2
    public/javascripts/vendor/sammy*.js

mobile:
  - *SAMMY1
  - *SAMMY2
  - public/javascripts/something_else.js

Alternativement, comme déjà suggéré, aplatir les listes imbriquées dans un extrait de code.

Note: selon yaml-online-parser, votre première suggestion n'est pas une utilisation valide de << (utilisé pour fusionner des clés de deux dictionnaires. L'ancre doit alors pointer vers un autre dictionnaire je crois.

47voto

sepp2k Points 157757

Si vous voulez que mobile soit égal à sammy, vous pouvez simplement faire :

mobile: *SAMMY

Cependant, si vous voulez que mobile contienne d'autres éléments en plus de ceux de sammy, il n'y a pas moyen de le faire en YAML à ma connaissance.

37voto

Jesse Beder Points 14026

Votre exemple est un YAML valide (un endroit pratique pour vérifier est YPaste), mais il n'est pas défini ce que fait la fusion. Selon le spécification, une clé de fusion peut avoir une valeur :

  1. Un mappage, auquel cas il est fusionné dans le mappage parent.
  2. Une séquence de mappages, auquel cas chacun est fusionné, un par un, dans le mappage parent.

Il n'y a pas de moyen de fusionner des séquences au niveau YAML.

Cependant, vous pouvez le faire en code. Utilisant le YAML de votre deuxième idée :

mobile:
  - *SAMMY

vous obtiendrez des séquences imbriquées - donc aplatissez-les ! En supposant que vous ayez un mappage de telles séquences imbriquées :

data = YAML::load(File.open('test.yaml'))
data.each_pair { |key, value| value.flatten! }

(Bien sûr, si vous avez un fichier YAML plus compliqué, et vous ne voulez pas aplatir toutes les séquences (ou elles ne sont pas toutes des séquences), vous devrez faire un peu de filtrage.)

1voto

flu Points 3120

Cette solution est uniquement pour Symfony/PHP (considérations pour d'autres langages, voir ci-dessous)

Note sur les clés de tableau de la page manuelle du tableau PHP:

Les chaînes contenant des entiers décimaux valides, à moins que le nombre ne soit précédé d'un signe +, seront converties en type int. Par exemple, la clé "8" sera en fait stockée sous 8. [...]

Cela signifie que si vous indexez réellement votre tableau ancre avec des clés entières, vous pouvez simplement ajouter de nouvelles clés en continuant la liste initiale. Ainsi, votre solution ressemblerait à ceci :

sammy: &SAMMY
  1: public/javascripts/vendor/sammy.js
  2: public/javascripts/vendor/sammy*.js

mobile:
  <<: *SAMMY
  3: public/javascripts/something_else.js

Vous pouvez même écraser des clés et en ajouter de nouvelles :

laptop:
  <<: *SAMMY
  1: public/javascripts/sammy_laptop.js
  3: public/javascripts/something_else.js

Dans les deux cas, le résultat final est un tableau indexé parfaitement valide, comme avant.


Autres langages de programmation

En fonction de votre implémentation YAML et de la manière dont vous itérez sur votre tableau, cela pourrait éventuellement être utilisé dans d'autres langages de programmation. Cependant, avec un avertissement.

Par exemple, en JS vous pouvez accéder aux clés de chaîne numériques par leur valeur entière également :

const sammy = {"1": "public/javascripts/vendor/sammy.js"}

sammy["1"]; // "public/javascripts/vendor/sammy.js"
sammy[1]; // "public/javascripts/vendor/sammy.js"

Mais vous devez garder à l'esprit, que votre tableau initial est maintenant un objet, et que vous devriez itérer en conséquence, par exemple :

Object.keys(sammy).forEach(key => console.log(sammy[key]))

-4voto

Eric Woodruff Points 1886

Comme cela a été suggéré, lorsque vous avez besoin d'aplanir une liste, du moins en ruby, il est trivial d'ajouter un spécificateur de type "!flatten" au mobile et de mettre en œuvre une classe qui étend Array, ajoute la balise yaml et aplatit le séquenceur de codage sur init_with.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X