Rails images in many folders - ruby-on-rails

I bought ready css and html template. There is many images in many folders, for example:
/images/folder_a/folder_a2/folder_a3/image.png
/images/folder_a/folder_s2/folder_s3/image.png
/images/folder_a/folder_b2/folder_b3/image.png
/images/folder_a/folder_z2/folder_z3/image.png
Is there some way in rails to do not write path to every image in view?
<%= image_tag('image.png') %>
gives not_found if I do not write path to it. I know I can copy all files to /images/ ...

You could write helpers for each of the major folders to cut down on having to repeat them. If they follow themes this would make sense (ie. icons, header images, borders, buttons etc.)

try these answer image_tag 'image.png' or image_url 'image.png'

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.

Is there an advantage to using link_to over the anchor tag in Rails?

Don't these two do the same thing?
<%= link_to "Example", '#', class: "somestyle" %>
Example
If I'm writing a static .html.erb page, if everything else is written with HTML tags, doesn't it make sense to use HTML tags for links as well? I'm not sure why one should use a helper. Similarly, for linking style sheets, javascripts, etc.
For the link tags, it may not make a difference which way you go. Unless you're linking to more than "#". For instance, using a routed path.
For the stylesheets and javascript, I think you will need to continue to use the Rails helpers if you're taking advantage of the asset pipeline. If so, the hash in the filename changes at each asset compilation (I believe), and manually trying to edit the filename each time could become a pain.

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.

How to change default path for images to look for

By default, rails is looking for images to "public/images" folder.
But it is not suiteable for me, since i have all the multimedia stuff in "public/data/:model/:id" folders.
How do i force rails to look into this folder.
I don't need obligatory such a pattern, that i mentioned above.
The only thing, i need, is just to change "public/images" path to "public/data", so, the rails should look to "data" folder, instead of "images".
I don't need to use "paperclip" plugin, because my models holding the pure HTML content (with clean and simple structure, that will not change in the future), that has "img" tags.
How can it be done ?
You you mean the image_tag helper is looking by default there? That's only the case if you only specify a relative path. Putting the full path in gets what you want I believe.
<%= image_tag '/data/model/1'
would generate
<img src="/data/model/1.png">

Resources