[RUBY] Convertir en balise dans la chaîne d'URL avec Rails

Dans le traitement du courrier sur rails, je voulais parfois convertir l'URL incluse dans la chaîne de caractères en une balise a.

Après quelques recherches, vous pouvez facilement obtenir l'URL de la chaîne de caractères en utilisant ʻURI.extract`. .. .. Je pensais que ce serait relativement facile à écrire, mais en fait il y avait pas mal de pièges et je suis resté coincé, alors j'ai décidé de l'écrire après l'avoir examiné.

TL;DR Le code final a été résolu en procédant comme suit. Comment en êtes-vous arrivé là? J'expliquerai pourquoi c'est bien plus tard.

def convert_url_to_a_element(text)
  uri_reg = URI.regexp(%w[http https])
  text.gsub(uri_reg) { %{<a href='#{$&}' target='_blank'>#{$&}</a>} }
end

text = 'url1: http://hogehoge.com/hoge url2: http://hogehoge.com/fuga'
convert_url_to_a_element(text)
=> "url1: <a href='http://hogehoge.com/hoge' target='_blank'>http://hogehoge.com/hoge</a> url2: <a href='http://hogehoge.com/fuga' target='_blank'>http://hogehoge.com/fuga</a>"

Anti-motif

Tout d'abord, comment écrire le mauvais processus. Cependant, même avec cela, le texte suivant peut être traité sans aucun problème. C'est pourquoi je n'ai pas immédiatement remarqué ce piège d'écriture cette fois. .. ..

def convert_url_to_a_element(text)
  URI.extract(text, %w[http https]).uniq.each do |url|
    sub_text = "<a href='#{url}' target='_blank'>#{url}</a>"
    text.gsub(url, sub_text)
  end
  text
end

text = 'url1: http://hogehoge.com url2: http://fugafuga.com'
convert_url_to_a_element(text)
=> 'url1: http://hogehoge.com url2: http://fugafuga.com'

En utilisant ʻURI.extract`, vous pouvez obtenir toutes les chaînes de caractères au format URL comme indiqué ci-dessous.

text = 'url1: http://hogehoge.com url2: http://fugafuga.com'
URI.extract(text, %w[http https])
=> ["http://hogehoge.com", "http://fugafuga.com"]

Ceci est remplacé en tournant chacun. Cependant, s'il est implémenté avec deux types d'URL avec le même nom de domaine, comme indiqué ci-dessous. .. ..

text = 'url1: http://hogehoge.com/hoge url2: http://hogehoge.com'
convert_url_to_a_element(text)
=> "url1: <a href='<a href='http://hogehoge.com' target='_blank'>http://hogehoge.com</a>/hoge' target='_blank'><a href='http://hogehoge.com' target='_blank'>http://hogehoge.com</a>/hoge</a> url2: <a href='http://hogehoge.com' target='_blank'>http://hogehoge.com</a>"

D'une manière ou d'une autre, il s'est vraiment effondré. .. ..

Cause

La cause est que le texte après une conversion de balise a également été remplacé dans le deuxième remplacement. Comme vous pouvez le voir, il y a un piège: ** cela ne fonctionne pas bien s'il y a deux URL ou plus avec le même nom d'hôte ** dans la méthode d'écriture ci-dessus.

contre-mesure

Vous pouvez empêcher le double remplacement en obtenant l'expression régulière et en la remplaçant par l'expression régulière dans le modèle gsub au lieu de transformer la chaîne de caractères obtenue par ʻURI.extract` par chacun.

def convert_url_to_a_element(text)
  uri_reg = URI.regexp(%w[http https])
  text.gsub(uri_reg) { %{<a href='#{$&}' target='_blank'>#{$&}</a>} }
end

Notes complémentaires

À propos de URI.regexp

ʻURI.regexp` est une méthode qui renvoie le modèle de la chaîne d'URL du schéma spécifié sous forme d'expression régulière. Puisqu'une expression régulière est une chaîne de caractères, vous pouvez l'écrire vous-même, mais cette méthode la crée rapidement.

Comme vous pouvez le voir à partir de la valeur de retour, je n'avais pas envie d'écrire ceci à partir de zéro. .. ..

URI.regexp(%w[http https])
=> /(?=(?-mix:http|https):)
        ([a-zA-Z][\-+.a-zA-Z\d]*):                           (?# 1: scheme)
        (?:
           ((?:[\-_.!~*'()a-zA-Z\d;?:@&=+$,]|%[a-fA-F\d]{2})(?:[\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*)                    (?# 2: opaque)
        |
           (?:(?:
             \/\/(?:
                 (?:(?:((?:[\-_.!~*'()a-zA-Z\d;:&=+$,]|%[a-fA-F\d]{2})*)@)?        (?# 3: userinfo)
                   (?:((?:(?:[a-zA-Z0-9\-.]|%\h\h)+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-fA-F\d]{1,4}:)*[a-fA-F\d]{1,4})?::(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)\]))(?::(\d*))?))? (?# 4: host, 5: port)
               |
                 ((?:[\-_.!~*'()a-zA-Z\d$,;:@&=+]|%[a-fA-F\d]{2})+)                 (?# 6: registry)
               )
             |
             (?!\/\/))                           (?# XXX: '\/\/' is the mark for hostport)
             (\/(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*(?:\/(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[\-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*)*)?                    (?# 7: path)
           )(?:\?((?:[\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))?                 (?# 8: query)
        )
        (?:\#((?:[\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))?                  (?# 9: fragment)
      /x

À propos de gsub

La méthode gsub elle-même peut être remplacée en passant une chaîne au lieu d'une expression régulière. Dans le premier cas, la chaîne de caractères de l'URL acquise est simplement transmise par chacun et remplacée, mais par conséquent, si l'URL contient le même domaine, la chaîne de caractères après une conversion de balise est également remplacée. Semble être exécuté, résultant en une chaîne de caractères étrange.

Si vous y réfléchissez, c'est vrai. .. .. J'étais inquiet parce que je ne pouvais pas penser à cette mesure. Tout d'abord, gsub

text.gsub!(uri_reg) { %{<a href="#{$&}">#{$&}</a>} }

À propos de URI.extract

Tout d'abord, ʻURI.extract` a été utilisé en premier, mais vous ne pouvez obtenir que la chaîne URL du texte en spécifiant le schéma. Je ne l'ai pas utilisé cette fois, mais cela me semblait pratique si je voulais simplement obtenir uniquement la chaîne d'URL.

text = 'aaaaa http://xxx.com/hoge bbbbb http://xxx.com'
URI.extract(text, %w[http https])
=> ["http://xxx.com/hoge" "http://xxx.com"]

Résumé

Il y a eu des rebondissements, mais je pense que c'était un bon code. Si vous avez un autre bon style d'écriture, faites-le moi savoir.

URL de référence

Recommended Posts

Convertir en balise dans la chaîne d'URL avec Rails
Convertir un tableau d'octets Java en une chaîne hexadécimale
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
Comment insérer une vidéo dans Rails
Notation pour mettre des variables dans une chaîne
[Android] Comment convertir une chaîne de caractères en resourceId
Conversion d'URL en chaîne
Code pour échapper aux chaînes JSON en Java
Ajoutez une fonction de balise aux rails. Utilisez actes-comme-taggable-on
Convertissez une chaîne en un tableau caractère par caractère avec Swift
Comment implémenter une fonctionnalité similaire dans Rails
Comment créer facilement un pull-down avec des rails
[Spring Boot] Comment obtenir des propriétés dynamiquement à partir d'une chaîne contenue dans une URL
Exemple de code pour convertir List en List <String> dans Java Stream
Comment implémenter une fonctionnalité intéressante dans Ajax avec Rails
Je veux utiliser une petite icône dans Rails
Lancer du SQL brut pour lire le réplica avec Rails
[Comment insérer une vidéo dans un hameau avec Rails]
Comment écrire une recherche de comparaison de dates dans Rails
Je souhaite définir une fonction dans la console Rails
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
Comment convertir un fichier en tableau d'octets en Java
[Rails 6] Comment définir une image d'arrière-plan dans Rails [CSS]
[Rails] Comment charger JavaScript dans une vue spécifique
Convertir le type String en type Timestamp
Convertir en chaîne Ruby Leet
Comment changer une chaîne dans un tableau en un nombre dans Ruby
Comment stocker des chaînes de ArrayList à String en Java (personnel)
Comment afficher des graphiques dans Ruby on Rails (LazyHighChart)
Fournir une barre de recherche dans Rails ~ Effectuer une recherche en joignant plusieurs tables
Appliquer le CSS à une vue spécifique dans Ruby on Rails
Ajoutez une fonction de recherche dans Rails.
Préparation à la création de l'application Rails
Créer une nouvelle application avec Rails
Implémenter un formulaire de contact dans Rails
Comment installer jQuery dans Rails 6
Comment installer Swiper in Rails
[Rails] Un moyen simple d'implémenter une fonction d'auto-introduction dans votre profil
Comment renommer un modèle avec des contraintes de clé externes dans Rails
À propos de la méthode de conversion d'une chaîne de caractères en entier / fraction (données de conversion) en Java
Comment implémenter la fonctionnalité de recherche dans Rails
[Rails] Je souhaite envoyer des données de différents modèles dans un formulaire
Comment changer le nom de l'application dans les rails
Comment mettre en œuvre un diaporama en utilisant Slick in Rails (un par un et plusieurs par un)
[Rails] Comment convertir ERB en Haml
Comment créer une requête à l'aide de variables dans GraphQL [Utilisation de Ruby on Rails]
Convertir les paramètres de demande en Enum au printemps