Rails: How to put stuff in header - ruby-on-rails

In my Rails App I included OneSignal which requires the following link to be placed in the head of the document:
<link href='/manifest.json' rel='manifest'>
Unfortunately with Rails I cannot put this link there, because the entire layout gets rendered inside the body.
While this ...
$(document).ready(function(){
$("head").append("<link href='/manifest.json' rel='manifest'>");
});
seems to work in development mode, it does not work in production.
How can I add this link to my head section of the document?

If you don't want to make a site wide change (adding the script to every page on the site) you can pick the page you want to put it on and add to the .htmlerb file
<%= content_for :header %>
<%= javascript_include_tag "script.js" %>
<%= end %>
javascript_include_tag will allow you to send content from the controller to the header and if script.js is in your app/assets/javascript directory, that will be added to the header.
Another option is to make a specific layout and have the pages that need the script use that layout, by calling it in the controller like so:
def users_index
#user= User.find(params[:id])
layout: users_index layout
end
That will load the users_index_layout.html.erb file from app/views/layouts...if it exists, and complain loudly if it does not.

You can add <link href='/manifest.json' rel='manifest'> in app/views/layouts/application.html.erb.

Related

Rails 4 Different background image for home and items index view

I should like to set two different background images for the home page of my app and the index view for the items.
I tried this directly in the home view:
<div class="container" style="background: url('/assets/images/hom.jpg')">
but it doesn't display any image. Someone can help me please?
I already have tried to follow this post but it still doesn't work.
How to set a different background image for each page in Rails 3 site?
Try it without /assets/ in the URL. The rails assets pipeline does not require you to state that it is in an /assets/ directory
You could achive this by setting the appropiate CSS class and setting the image background in you stylesheets. Something like:
<div class="container home">
And in a SCSS file:
.container.home{
background-image: image-url("hom.jpg");
}
Keep in mind that image-url is a helper that should be used in .scss files.
I tried this in my pages:
<div style="background-image: url('/assets/hom.jpg')">
And it seems to work locally, but after a push on Heroku the images aren't displayed online.
In addition, the image appears cut, because is referred to a DIV, and I want it referred to the body of my pages.
One way to do this is by adding the controller and action names to the body tag in your layout. Then you can rely on pure CSS to serve different images. In your layout file you can do this:
<%= content_tag :body, class: "#{controller_name}-#{action_name}" do %>
<!-- Your layout content, or everything that should be in the body tag goes here -->
<% end %>
This would give you the following HTML:
<body class="items-index> <!-- or whatever the current controller/action are -->
Then, you can add the relevant CSS.
.items-index {
background-image: image-url("items_index.jpg");
}
.pages-home {
background-image: image-url("pages_home.jpg");
}
You can wrap this in a helper to make it cleaner.
def class_for_body
"#{controller_name}-#{action_name}"
end
Or even:
def body_tag(&block)
content_tag :body, yield, class: "#{controller_name}-#{action_name}"
end
See controller_name and action_name methods provided by Rails.

Ruby on Rails : conditionally load scripts?

Hey,
I want to be able to put all of my pages' scripts in my application layout, and load each one for the appropriate page.
I came across this [question][1], and I thought I can put the scripts inside of partials and do it the same way that is indicated in the mentioned question, however I'm trying to find the best way for scripts.
Would it be something like :
yield :scripts if condition
or
unless condition
content_for scripts do
end
end
or any other 'best' way ?
Note: Each page has its own script saved under the same name of the page.
Solved
I relied on the recommendations of #damien at the comments with the link he provided to come up with something like this:
In my helpers:
def javascript_exists?(script)
script = "#{Rails.root}/app/assets/javascripts/#{[params[:controller], params[:action]].join('_')}.js"
File.exists?(script) || File.exists?("#{script}.coffee")
end
In my application layout:
<%= javascript_include_tag [params[:controller], params[:action]].join('_'), :media => "all" if javascript_exists?([params[:controller], params[:action]].join('_')) %>
So to each controller, and to each action in the controller, the appropriate .js file gets included if it exists.

Setting up meta data for a Rails Website

I have been struggling to figure out how to place my meta data for all pages. The head tag where the meta data must be placed is on application.html.erb. My approach at first which I later found as a bad practice was to check the URL path, like: if request.original_fullpath == '/faq' to show the meta data for the FAQ page.
Despite being a bad practice, this couldn't help on pages that are dynamic (like the user's profile pages). Then I decided to take a simple approach and make it work. I added the meta tags on each page individually. I was naive thinking that can be overridden by using the head tag on each page. So I was wondering, how do I set the meta tags/data for each page on Rails? What's your approach?
The content_for helper might work well.
# app/views/layouts/application.html.erb
<head>
<%= content_for :meta_tags %>
</head>
# app/views/posts/show.html.erb
<% content_for :meta_tags do %>
...
<% end %>

RoR stylesheet layout view link. What does `:media => all` mean

I have:
<&= stylesheet_link_tag "application", :media => "all" %>
but I am adding a (completely) alternative layout for some of the views in my application, with separate stylesheets. I would like to link the existing layout to only some of the stylesheets, and add others. What do I need to change here?
for this you can create new file in views/layout as similar to your application.html.erb
for example i am creating home.html.erb.Link your all stylesheets and js files in that and finally just add that layout name in your required controller as layout 'home'
You can use separate manifest file and include those manifest file
This answer will help you how to do this
It specifies that your application.css should be loaded when the page is viewed in all media types. It's a CSS property, not a Rails property.
See http://www.w3.org/TR/CSS2/media.html#media-sheets for more details.
You can add a separate layout for whole controller or for specific actions
For example:
in your controller:
layout :resolve_layout
#controller code
...
def resolve_layout
case action_name
when "new", "create", "wait_conformation"
"customer_layout"
else
"producer_layout"
end
end
Here customer_layout & producer_layout are layout files.

Rails: using "content_for" after the corresponding "yield" inside layout

I think this has been asked before but even though I searched Google I haven't come up with a solution.
So this is what I'm trying to do in Rails 2.3.5:
layouts/application.html.erb:
<html>
<head>
... some other stuff
<%= yield :head %>
</head>
<body>
<% content_for :head, "something that belongs in the head" %>
</body>
</html>
Notice the yield before the content_for.
I know that Rails - by default - doesn't allow the content of :head to be defined after yield has been used - makes sense.
I even tried hooking into the template render process but no success so far.
So my goal is to be able to define content_for inside partials/templates and have the "yield" somehow delayed and executed just before the response is send to the browser.
Has somebody come up with a solution?
Greetings and thanks,
Frank
Update
I'll go with weppos's idea and try myself on rack middleware. thanks
The rendering process first loads and executes the action template, then decorates the template with the selected layout.
The layout is rendered from top to botton, thus you can't add more content to :head after :head is already rendered.
You need to change your strategy. Either place the fragment in a partial and attach it to your action views or use a post-processing strategy such as a Rack module/after_filter to alter the html code directly.
I probably would try to find a better solution based on what I actually need. If you are encountering this issue, chances are the error is somewhere else, perhaps in the app architecture.
There shouldn't be an equals sign in your content_for statement. It should be:
<% content_for :head, "Something that belongs in the head" %>
If you define the content within your templates and partials then it should work. This technique was covered in Railscast episode 8.

Resources