Initial seed access asset link - ruby-on-rails

I have an initial seed that I am trying to add some html to the database. I would like to reference an image. But when I do this it does not contain the auto generated hash key.
Here is the code I have:
<img src=\"/assets/Placeholder.png\" alt=\"Add image 2\">
But I would like to use the actual production file.
If I was in a view i would use
<%= image_tag "Placeholder.png" %>
Is this possible in the initialseed file?

If you pre-compile assets in production, it should generate a manifest.yml file with the respective fingerprint/hash for the file in question. You could do that and then use that hash in your seed, I believe.

Related

Rendering images from root with image_tag

I have a folder in my root 'root/tmp/database/*.JPG' that I want to show in my view with a image_tag.
My current code for this is:
<% #images.each do |image| %>
<%= image_tag image.file, class: "img-responsive" %>
<% end %>
But because image_tag uses the asset pipeline it renders the images as:
'/images/tmp/database/xotter-1.jpg'
So my question is, is it possible that I use an image_tag and get the images rendered as: '/tmp/database/*.JPG'
All assets (images, css, js etc) served in your website need to come from somewhere inside the public folder. However, the public folder can contain symbolic links, aka shortcuts, to other folders.
So, for example, if you want to serve files from #{Rails.root}/tmp/database you can make a symbolic link like so:
#from your application folder
cd public
ln -s ../tmp/database database
You should now have the appearance of having the database folder inside your public folder, and can link to a file in it with the url
"/database/xotter-1.jpg"
which corresponds to a file at
#{Rails.root}/public/database/xotter-1.jpg
These instructions assume you are in a bash-style command line shell, eg in linux or mac os. If you are in windows you may need to set the shortcut up differently.
EDIT: an answer to your follow up question about displaying all images in a folder.
Let's say you have a folder #{Rails.root}/public/database and you want to find all jpg files in it: you can do that in a variety of ways. I like Dir[], used with File.join (which is a safe way to generate file paths which accounts for extra/missing slashes, which are otherwise easy to get wrong by mistake) eg
jpg_files = Dir[File.join("public/database", "*.jpg")]
=> ["public/database/foo.jpg", "public/database/bar.jpg"]
Note that these paths are all relative to where the command is run from, which in the case of a rails server or console is the rails application folder.
If you want to link to these, you will need the path relative to the public folder, which you can get by saying
filename.gsub("public","")
=> "/database/foo.jpg"
So, to tie this together, in your template:
<% Dir[File.join("public/database", "*.jpg")).each do |file| %>
<%= image_tag file.gsub("public",""), class: "img-responsive" %>
<% end %>
Just to add to Max Williams' epic answer, if you populate your public folder with your images (instead of tmp), you'll be able to use the built-in asset_path helpers:
Computes the path to asset in public directory
asset_path "database/xotter-1.jpg" #-> /public/assets/database/xotter-1.jpg"
I appreciate this means you have to use the assets subdirectory, but there is a good reason for this...
--
Precompilation
Personally, I would put the images into the assets/images folder of your app.
The problem you'll have is that all of your images will remain "naked" in your public folder, which will both leave them open to hotlinking, but also prevent their proper use in the asset pipeline.
If you include the images in assets/images/...., you get to precompile the images when you push to production:
rake assets:precompile RAILS_ENV=production
Precompilation puts all the assets into the /public folder anyway... but more importantly, fingerprints them:
public/assets/images/database/xotter-1-[[fingerprint]].jpg
These images will still be available if you call image_tag databsae/xotter-1.jpg, but this time they'll be in their correct place.
All paths in Rails are taken from the public dir, so you can reference a link to the public dir directly, by using a relative path:
image_tag 'database/xotter-1.jpg
The difference is that if you put your images into assets/images, they are included in the asset pipeline, and thus will be accessible regardless of the environment you're running your app in.

how to insert image in rails

Using Rails, I am creating my first web-site. And I have a problem like this: I can't insert an image in my page (index.html.erb).
I put an image named "main.png" in directory "app/assets/images", and wrote that:
<img src="main.png">
But my image isn't displayed correctly. What I'm doing not right?
You should use the provided helpers by Rails to "automagically" detect paths, fingerprints, ...:
<%= image_tag "main.png" %>
Anyway, I recommend you to read the asset pipeline guides to understand how the assets works in Rails: http://guides.rubyonrails.org/asset_pipeline.html
You should use Rails helpers as markets pointed out.
By the way, the name of the image file should be the same you use as the parameter of image_tag method. You are referencing your image as main.png when the image file is main.jpg
<%= image_tag "main.jpg" %>

Absolute image URL in rails

How can I get the absolute URL of an image in Rails.
Rails serves the images using assets.
So an image by the name "logo.png" is actually stored as "logo-776bfb0d3b4bdea029da753cf63916e2.png".
This is not a problem when I need to access the image using a Rails server as I render it using the <%= image_tag %> helper.
But I need to pass the actual URL to an API which will then render the image.
So how can I just get the physical URL??
This is the name of the file. It will be in your public/assets directory and the url will be
your-site-name/assets/logo-776bfb0d3b4bdea029da753cf63916e2.png.
Note this will change when you precompile your assets and the file is given a new fingerprint. You will be much better off using the rails image_url helper to give you the URL and passing that to your API.
If you are using rails 4. Then the image will be in name_of_your_app/app/assets/images/.
You probably have to include ActionView::Helpers::AssetUrlHelper. Or you could just call ActionController::Base.helpers.image_tag("image.png")

How should I access the asset_url helper in the view

When I try to use asset_url in my view (Rails 3.2), I get a NoMethodError.
What do have to do to be able to use AssetUrlHelper's methods in my views?
To explain this a bit better and maybe find an alternative solutions: I need to get an "asset link" to file attachments created with carrierwave.
My model has an attachment which points to a file in my assets directory. I need to draw a link to this file.
= link_to model.name, model.attachment(:size)
gives me /myfiles/model/id/attachment/size.png (which is what is persisted by carrierwave)
= image_tag model.attachment(:size)
gives me the wanted http://static_host.com/.../size.png
but I have no need for an image tag, but the plain link to the file at the asset host.
The following works ok for me:
<%= link_to "link to asset", asset_path(article.image.url) %>
I'm using paperclip but I doubt it makes much difference
I think the helper asset_path belongs to asset files (like .css and .js) , not views. In views is proper to be used helpers like image_tag or stylesheet_include_tag. This is the idea behind the asset-pipeline - to ease reference to assets.

Rails asset pipeline - how to include asset not in asset path?

I've converted this multi skinned app of mine to make use of the assets pipeline introduced in Rails 3.1. For the most part it's been surprisingly easy and I'm in love with the preprocessing ability which allows you to use inline Ruby in your CSS/JS files.
I have run into a major problem though, which despite the power of Sprockets seems tricky to solve. My app can be run with any number of skins (or "identities" rather) which is chosen at runtime. This "identity" parameter sets up stuff like cache directory, database connection, view paths - and indeed asset paths. While all "identities" can have their own stylesheet there is also a shared one which is used across all instances. So the assets folder structure looks something like this:
In /app/assets/stylesheets/aplication.css.erb:
<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>
This loads two stylesheets, and crucially it uses the configured asset paths to resolve them (that's why i use require_assets instead of the standard require and include directives, as they don't hit the resolver). It returns the first matches found and allows me to very easily override part or whole of the default styling. So
/app/assets/stylesheets/shared.css
can be overridden by putting a file with the same name in the instance assets folder
/app/assets/[identity]/stylesheets/shared.css
and if no such file exists it silently falls back to the default shared.css.
It all works brilliantly - I use the same technique for JavaScripts, images and fonts and everything gets neatly processed and packaged during precompilation. BUT. There is a type of (sideways) inheritance that I'm unable to achieve; sometimes the skin for an identity is so similar to another one that only a few dozen lines differ (e.g. identical layout but with a different color scheme) and I really want to be able to do something like this:
assets/stylesheets/application.css.erb:
<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>
assets/current_identity/stylesheets/overrides.css:
<% require_asset("../../some_other_identity/stylesheets/overrides.css") %>
/* followed by the dozen or so lines that differ for this skin */
...
This FAILS because in the current context "some_other_identity" is not in the asset paths - Rails does not find the file in dev mode, and of course it's not included during precompilation either. And if I do include it in the assets path it loads the wrong overrides.css (there can be only one). So I've been experimenting with putting something like this at the top of overrides.css:
<%= File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css")) %>
/* rest of CSS */
...
And indeed that works just as expected. BUT. Because I'm now using the assets pipeline to serve all assets I can no longer reference images in the CSS with a fixed path - I have to use <%= asset_path("some_image.png") %> so that the path resolver can work its magic. This means my overrides.css is really overrides.css.erb, and of course the ERB preprocessing doesn't happen when you do File.read(). So, I'm stuck! Help! Anyone?
Edit: If I use
<%= ERB.new(File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb"))).result %>
it does try to parse the ERB, but I get
undefined method `asset_path' for main:Object
which of course is due to me using asset_path("some_image.png") etc in the file I'm trying to include.
Ok, after hours of searching I came upon the list of available helper methods in Sprockets - it would have saved me a lot of time had this been linked to from the Sprockets man page on GitHub (there is a link, but it points to #FIXME). From the Sprockets API docs:
(Object) evaluate(path, options = {})
Reads path and runs processors on the file.
This allows you to capture the result of an asset and include it directly in another.
<%= evaluate "bar.js" %>
Bingo! I changed my include directive to:
<%= evaluate(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb")) %>
and the CSS gets processed and the results inserted, just the way I wanted it to work.

Resources