web-dev-qa-db-fra.com

URL complète pour un chemin d’image dans Rails 3

J'ai une image, qui contient les téléchargements de carrierwave: 

Image.find(:first).image.url #=> "/uploads/image/4d90/display_foo.jpg"

À mon avis, je veux trouver l'URL absolue pour cela. L'ajout de root_url donne un double /.

root_url + image.url #=> http://localhost:3000//uploads/image/4d90/display_foo.jpg

Je ne peux pas utiliser url_for (à ma connaissance), car soit permet de passer un chemin, ou une liste d'options permettant d'identifier la ressource et l'option :only_path. Comme je n'ai pas de ressource identifiable via "controller" + "action", je ne peux pas utiliser l'option :only_path

url_for(image.url, :only_path => true) #=> wrong amount of parameters, 2 for 1

Quel serait le moyen le plus propre et le meilleur de créer un chemin vers une URL complète dans Rails3?

35
berkes

essayez la méthode path

Image.find(:first).image.path

UPD

request.Host + Image.find(:first).image.url

et vous pouvez l'envelopper comme aide pour le DRY pour toujours

request.protocol + request.Host_with_port + Image.find(:first).image.url
33
fl00r

Vous pouvez également définir le paramètre de configuration asset_Host de CarrierWave comme suit:

# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.storage = :file
  config.asset_Host = ActionController::Base.asset_Host
end

Ceci ^ indique à CarrierWave d’utiliser le paramètre config.action_controller.asset_Host de votre application, qui peut être défini dans l’un de vos fichiers config/envrionments/[environment].rb. Voir ici pour plus d'informations.

Ou définissez-le explicitement:

  config.asset_Host = 'http://example.com'

Redémarrez votre application et vous êtes prêt à partir - aucune méthode d'assistance n'est requise.

* J'utilise Rails 3.2 et CarrierWave 0.7.1

95
ncherro

Une autre méthode simple à utiliser est URI.parse. Dans votre cas, ce serait: 

require 'uri'

(URI.parse(root_url) + image.url).to_s

et quelques exemples:

1.9.2p320 :001 > require 'uri'
 => true 
1.9.2p320 :002 > a = "http://asdf.com/hello"
 => "http://asdf.com/hello" 
1.9.2p320 :003 > b = "/world/hello"
 => "/world/hello" 
1.9.2p320 :004 > c = "world"
 => "world" 
1.9.2p320 :005 > d = "http://asdf.com/ccc/bbb"
 => "http://asdf.com/ccc/bbb" 
1.9.2p320 :006 > e = "http://newurl.com"
 => "http://newurl.com" 
1.9.2p320 :007 > (URI.parse(a)+b).to_s
 => "http://asdf.com/world/hello" 
1.9.2p320 :008 > (URI.parse(a)+c).to_s
 => "http://asdf.com/world" 
1.9.2p320 :009 > (URI.parse(a)+d).to_s
 => "http://asdf.com/ccc/bbb" 
1.9.2p320 :010 > (URI.parse(a)+e).to_s
 => "http://newurl.com" 
10
c2h2

Prenant juste la réponse du parquet et fournissant l'aide

# Use with the same arguments as image_tag. Returns the same, except including
# a full path in the src URL. Useful for templates that will be rendered into
# emails etc.
def absolute_image_tag(*args)
  raw(image_tag(*args).sub /src="(.*?)"/, "src=\"#{request.protocol}#{request.Host_with_port}" + '\1"')
end
5
M.G.Palmer

Il y a tout un tas de réponses ici. Cependant, je n’ai aimé aucun d’entre eux, car ils comptent tous sur moi pour rappeler d’ajouter explicitement le port, le protocole, etc. Je trouve que c’est la manière la plus élégante de procéder:

full_url = URI( root_url )
full_url.path = Image.first.image.url
# Or maybe you want a link to some asset, like I did:
# full_url.path = image_path("whatevar.jpg")
full_url.to_s

Et ce qui est bien, c'est que nous pouvons facilement changer une chose et peu importe la raison, vous le faites toujours de la même manière. Dites si vous voulez supprimer le protocole et que vous utilisez le RL relative au protocole , faites-le avant la conversion finale en chaîne.

full_url.scheme = nil

Oui, j’ai maintenant un moyen de convertir les URL de mon image d’immobilisation en URL du protocole que je peux utiliser dans un extrait de code que d’autres voudront peut-être ajouter sur leur site. Elles fonctionneront quel que soit le protocole utilisé sur leur site (à condition que votre site supporte l'un ou l'autre protocole).

2
Timo

J'ai utilisé default_url_options, car request n'est pas disponible dans le programme de messagerie et j'ai évité la duplication du nom d'hôte dans config.action_controller.asset_Host si je ne l'avais pas spécifié auparavant.

config.asset_Host = ActionDispatch::Http::URL.url_for(ActionMailer::Base.default_url_options)
2
Eugene

Vous ne pouvez pas faire référence à un objet de requête dans un courrier électronique.

def image_url(*args)
    raw(image_tag(*args).sub /src="(.*?)"/, "src=\"//#{ActionMailer::Base.default_url_options[:protocol]}#{ActionMailer::Base.default_url_options[:Host]}" + '\1"')
end
1
Luke W

Vous pouvez réellement y arriver facilement en

root_url[0..-2] + image.url

Je conviens que ça n'a pas l'air bien, mais que le travail est fait .. :)

1
Alfie

J'ai trouvé cette astuce pour éviter le double slash:

URI.join(root_url, image.url)
0
hlcs