Rails: simple asset pipeline issue with images breaking - ruby-on-rails

I have an Item and each item has a string image column where I store the path to an image in assets like assets/images/items/1.jpg
If I call some_item.image, then I'll receive the path to that image like "/assets/items/1.jpg"
If I go into a view and write <img src="/assets/items/1.jpg"> then I will see the proper image. But with image_tag <%= image_tag(some_item.image) %>, the image tag is populated like <img src="images/assets/items/1.jpg"> which does not properly show the image.
How do I fix this?

Instead of image_tag, you should use the image_path() or image_url() helpers instead.
consider the following:
img = 'some_image.png'
image_tag(img) #=> <img src="some_image.png"/>
image_path(img) #=> <img src="/assets/some_image.png"/>
image_url(img) #=> <img src="http://host.ext/assets/some_image.png"/>

I suggest you to define a method on your Item model which return a valid path for image_tag:
Example:
def image_path
self.image_path.sub(/^\/assets\//, '')
# removes '/assets/' from the start of the string
# returns a String like 'items/1.png'
end
in your view:
= image_tag(item.image_path)

Related

how to get the image from the url without downloading it but store it in a variable in ruby

How to fetch the image from its URL and store it in a variable
As im having a URL of a image, i need to fetch that image and then store it in variable and display the image in the variable using the rails image tag, so how to approach this..
Thanks in advance
the method i tryed
require 'open-uri'
imagevar = open(url).read
img_tag(imgvar)
which resulted in following error
ActionView::Template::Error: string contains null byte
so what will the correct solution to approach this
To assign the URL to a variable in your .erb, do the following.
<% image_url = "<image_url>" %>
To render the image from the URL you can use image_tag
<%= image_tag image_url %>

How can I get url of image variant in model (outside of controller/view)? Active Storage

I can get url in model with this code (Active Storage)
Rails.application.routes.url_helpers.rails_blob_path(picture_of_car, only_path: true)
But I need to get url of a resized variant
picture_of_car.variant(resize: "300x300").processed
For example this code
Rails.application.routes.url_helpers.rails_blob_path(picture_of_car.variant(resize: "300x300").processed, only_path: true)
throw
NoMethodError (undefined method `signed_id' for #< ActiveStorage::Variant:0x0000000004ea6498 >):
Solution:
Rails.application.routes.url_helpers.rails_representation_url(picture_of_car.variant(resize: "300x300").processed, only_path: true)
Answer provided here.
for a variant you need to use rails_representation_url(variant) - this will build a url similar to the one that rails_blob_url builds but specifically for that variant.
variant = picture_of_car
.variant(resize: '300x300')
.processed
variant.service.send(:path_for, variant.key) # Absolute path to variant file
Following the documentation at https://api.rubyonrails.org/classes/ActiveStorage/Variant.html it should be:
picture_of_car.variant(resize: [300, 300]).processed.service_url
👋🏻 Just adding on here, if you're just needing a url for an Active Storage attachment to pass to an HTML element that Rails doesn't have a native *_tag method for, you can use url_for in scope and it'll work. In my case it was a <picture> tag. For an image it's easy:
<%= image_tag #thing.foo_image.variant(:medium), class: "mx-auto" %>
For a <picture> tag (no native picture_tag helper) it's almost as easy:
<picture>
<source srcset="<%= url_for(#thing.foo_image.variant :large) %>">

How do you display a png image in string format in Rails?

I have a function in Ruby that returns the data for a QR Code image in PNG format that works as follows:
puts generate_qr_code("this is a test")
�PNG
IHDk�XTPLTE,�)�[��tRNS#��f�IDATx���Kr��M�ѭ8)
�<��q����(�x��H�$I�$I�$I�$I�$�+����
What would be the simplest way to take this string and display in a Rails view?
I have a couple of ideas on how this could be possilbe such as saving the data in a #img_data variable and the view some how displaying it. Or perhaps saving into a file and passing it's url. The images generated will only be used temporarily so saving the data somewhere wouldn't be necessary.
What would be the simplest way to take this string and display in a Rails view?
Construct a data URI using the Base64-encoded image data and pass it to the image_tag helper:
# controller
def show
#image_data = generate_qr_code('this is a test')
end
# view
<%= image_tag "data:image/png;base64,#{Base64.strict_encode64(#image_data)}" %>
You could also wrap this in a helper method:
# helper
def qr_image_tag(text, options = {})
image_data = generate_qr_code(text)
data_uri = "data:image/png;base64,#{Base64.strict_encode64(image_data)}"
image_tag(data_uri, options)
end
# view
<%= qr_image_tag('this is a test') %>
def render_qr_code
response.headers['Cache-Control'] = "public"
response.headers['Content-Type'] = "image/png"
response.headers['Content-Disposition'] = "inline"
render :body => generate_qr_code("this is a test")
end
Then in you view you do <img src="controller_name/render_qr_code">. You need a route etc...

Rails - slice string and rails path

I do some string slice. Right now i have something like this:
#str = '/images00.someother.path_to_.image.jpg' ///my spliced string
When i do this:
#new_string = #str[1..#str.length]
i thought that i will have string like:
'images00.someother.path_to_.image.jpg'
but no... rails put in url path to images, so the output is:
<img src='/images/images00.someother.path_to_.image.jpg'>
when i slice more it looks like 'images/ages01... etc.
How can i remove this default path but only for this action in controller?
VIEW:
<% #array.each do |a| %>
<%= image_tag(a, :id => 'image_' %>
If you mean you don't want the "/images" to appear
just remove the
#new_string = #str[1..#str.length]
if you pass the path with a starting slash rails won't add the default image path
so the output would be
<img src='/images00.someother.path_to_.image.jpg'>
which is the images00.someother.path_to_.image.jpg in your public directory
If you're testing in production mode, rails by default don't serve the static files.
You should change it on config/environments/production.rb the line:
config.serve_static_assets = false
As long as the question is missing some details, it might help :)

Rails 3.1: Trouble on displaying images in mailer view files

I am using Ruby on Rails 3.1 and I would like to add my web site logo (that is, an image handled through the new Asset Pipeline) to an e-mail.
If in my mailer view file I state the following:
<% # Note: '#root_url' is my application hostname (eg: http://www.mysite.com) %>
<%= link_to image_tag( "#{#root_url.to_s}/images/logo.png"), #root_url.to_s %>
it doesn't work in production mode (that is, I cannot display the logo image) because I think the Asset Pipeline uses the Fingerprinting technique and in the received e-mail it doesn't. Inspecting the HTML logo element in the e-mail I get something like this:
<img src="http://www.mysitecom/images/logo.png"> # without Fingerprinting
How can I solve the problem?
In my production.rb file I have the following commented out code:
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
in config/environments/production.rb (and other enviroment files needed) add:
config.action_mailer.asset_host = 'http://mysite.com'
after that rails will automatically add hostname in front of paths generated by image_tag
# haml
= image_tag 'foo.jpg'
will become
#html
<img alt="" src="http://mysite.com/assets/foo.jpg" >
...same apply for image_path
#haml
%table#backgroundTable{background: image_path('email-background.jpg'), width: '100%', :border => "0", :cellpadding => "0", :cellspacing => "0"}
will become
<table background="http://mysite.com/assets/email-background.jpg" border="0" cellpadding="0" cellspacing="0" id="backgroundTable" width="100%">
watch out!!!
# this will make your emails display images
config.action_mailer.asset_host = 'http://mysite.com'
is different than
# this wont make your email images work
config.action_controller.asset_host = "http://mysite.com"
All of these answers are assuming you're using the asset pipeline, but from your example, you're specifying an image in /public/images - this is not part of the asset pipeline, so all the asset_path based answers won't work, and further your initial fingerprinting supposition is incorrect.
If you put an image in /public/images, you want your image tag to have a src of http://yoursite.com/images/the-image.jpeg, no fingerprint, no asset path, nothing - just hard-code it into your view:
<img src="<%=#root_url%>/images/logo.png">
But, you have to actually have the file in that location! If you have your image in /app/assets/images, then you'll need to use image_tag and the asset pipeline as others have answered.
An alternative is to include the image logo in the mail. The mail could also be viewed offline. You can add the logo in you Mailer class, with the following code..
attachments["your_logo.png"] = File.read("#{Rails.root}/assets/images/your_logo.png")
This code will include your image to the mail. I believe when you want to show your attachment in the mail you need to do the following:
Class YourMailer < ActionMailer::Base
def sendmail
.....
attachments.inline['your_logo.png'] = File.read("#{Rails.root}/assets/images/your_logo.png")
end
And in your sendmail.html.erb view you can use the image_tag method:
<%= image_tag attachments['your_logo.png'].url %>
note: if the mail does not get shown correctly you can alternatively try the solution at:
Rails attachments inline are not shown correctly in gmail
Your mail can then also be viewed offline correctly.
Have you tried adding something like this
config.action_mailer.default_url_options = { :host => 'www.example.com' }
to your config/enviroments/production.rb file
Try:
<%= link_to image_tag( "#{#root_url.to_s}/assets/logo.png"), #root_url.to_s %>
You're giving image_tag an absolute url so it thinks it doesn't need to do any fingerprinting or anything else other than regurgitate the string you gave it. I would try
link_to( image_tag('logo.png'), #root_url)
You'll also need to set actioncontroller's asset host to get rails to generate a full url for the image rather than just a path
One caveat to note: if you change the image then the fingerprint will obviously change and so the inage URL in all of your previously sent emails will become invalid. You may wish to consider inline images, although obviously these increase the email size
Try out this one
<%= link_to image_tag( asset_path, 'logo.png'), #root_url.to_s %>
Adding mode:'rb' worked for me:
attachments.inline['Logo.jpg'] = File.read(File.join(Rails.root,'app','assets','images','Logo.jpg'), mode: 'rb')
If you compile your assets:
RAILS_ENV=production bundle exec rake assets:precompile
and use asset_path in your view:
<%= link_to image_tag( asset_path('logo.png') ), #root_url.to_s %>
--it should work in both development and production. This is the way I do it my views, and .css.scss.erb stylesheets. I assume that it doesn't make a difference that it is a view for a mailer.
make sure your html page have follwing header
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
and render image as:
<%= image_tag('http://'+#url+'/images/header.jpg')%>
or
if you want link to image then
<%= link_to image_tag('http://'+#url+'/images/header.jpg'),root_path %>
#url = 'your website address'

Resources