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>"
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é. .. ..
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.
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
ʻ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
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>} }
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"]
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.
Recommended Posts