Rails 3 - Ideal way to set title of pages - ruby-on-rails-3

Whats the proper way to set the page title in rails 3. Currently I'm doing the following:
app/views/layouts/application.html:
<head>
<title><%= render_title %></title>
<%= csrf_meta_tag %>
app/helpers/application_helper.rb:
def render_title
return #title if defined?(#title)
"Generic Page Title"
end
app/controllers/some_controller.rb:
def show
#title = "some custom page title"
end
Is there another/better way of doing the above?

you could a simple helper:
def title(page_title)
content_for :title, page_title.to_s
end
use it in your layout:
<title><%= yield(:title) %></title>
then call it from your templates:
<% title "Your custom title" %>

There's no need to create any extra function/helper. You should have a look to the documentation.
In the application layout
<% if content_for?(:title) %>
<%= content_for(:title) %>
<% else %>
<title>Default title</title>
<% end %>
In the specific layout
<% content_for :title do %>
<title>Custom title</title>
<% end %>

I found that apeacox's solution didn't work for me (in Rails 3.0.3).
Instead I did...
In application_helper.rb:
def title(page_title, options={})
content_for(:title, page_title.to_s)
return content_tag(:h1, page_title, options)
end
In the layout:
<title><%= content_for(:title) %></title>
In the view:
<% title "Page Title Only" %>
OR:
<%= title "Page Title and Heading Too" %>
Note, this also allows us to check for the presence of a title and set a default title in cases where the view hasn't specified one.
In the layout we can do something like:
<title><%= content_for?(:title) ? content_for(:title) : 'This is a default title' %></title>

This is my preferred way of doing it:
application_helper.rb
module ApplicationHelper
def title(*parts)
content_for(:title) { (parts << t(:site_name)).join(' - ') } unless parts.empty?
end
end
views/layouts/application.html.erb
<title>
<%= content_for?(:title) ? yield(:title) : t(:site_name) %>
</title>
config/locales/en.yml
en:
site_name: "My Website"
This has the nice advantage to always falling back to the site name in your locales, which can be translated on a per-language basis.
Then, on every other page (eg. on the About page) you can simply put:
views/home/about.html.erb
<% title 'About' %>
The resulting title for that page will be:
About - My Website
Simples :)

#akfalcon - I use a similar strategy, but without the helper.. I just set the default #title in the application controller and then use, <%=#title%> in my layout. If I want to override the title, I set it again in the controller action as you do. No magic involved, but it works just fine. I do the same for the meta description & keywords.
I am actually thinking about moving it to the database so an admin could change the titles,etc without having to update the Rails code. You could create a PageTitle model with content, action, and controller. Then create a helper that finds the PageTitle for the controller/action that you are currently rendering (using controller_name and action_name variables). If no match is found, then return the default.
#apeacox - is there a benefit of setting the title in the template? I would think it would be better to place it in the controller as the title relates directly to the action being called.

I prefer this:
module ApplicationHelper
def title(*page_title)
if Array(page_title).size.zero?
content_for?(:title) ? content_for(:title) : t(:site_name)
else
content_for :title, (Array(page_title) << t(:site_name)).join(' - ')
end
end
end
If title is called without arguments, it returns the current value of title or the default which in this example will be "Example".
It title is called with arguments, it sets it to the passed value.
# layouts/application.html.erb
<title><%= title %></title>
# views/index.html.erb
<% title("Home") %>
# config/locales/en.yml
en:
site_name: "Example"

You can also check this railscast. I think it will be very useful and give you basic start.
NOTE: In case you want more dynamic pages with pjax

I have a somewhat more complicated solution. I want to manage all of my titles in my locale files. I also want to include meaningful titles for show and edit pages such that the name of the resource is included in the page title. Finally, I want to include the application name in every page title e.g. Editing user Gustav - MyApp.
To accomplish this I create a helper in application_helper.rb which does most of the heavy lifting. This tries to get a name for the given action from the locale file, a name for the assigned resource if there is one and combines these with the app name.
# Attempt to build the best possible page title.
# If there is an action specific key, use that (e.g. users.index).
# If there is a name for the object, use that (in show and edit views).
# Worst case, just use the app name
def page_title
app_name = t :app_name
action = t("titles.#{controller_name}.#{action_name}", default: '')
action += " #{object_name}" if object_name.present?
action += " - " if action.present?
"#{action} #{app_name}"
end
# attempt to get a usable name from the assigned resource
# will only work on pages with singular resources (show, edit etc)
def object_name
assigns[controller_name.singularize].name rescue nil
end
You will need to add action specific texts in your locale files in the following form:
# en.yml
titles:
users:
index: 'Users'
edit: 'Editing'
And if you want to use meaningful resource names in your singular views you may need to add a couple of proxy methods, e.g.
# User.rb
def name
username
end

I thought it will be good:
<title>
<% if #title %>
<%= #title %>
<% else %>
Your title
<% end %>
</title>
And give a value to #title in your controller, or the title will be Your title

My answer is more simple:
locales/any_archive.yml:
pt-BR:
delivery_contents:
title: 'Conteúdos de Entregas'
groups:
title: 'Grupos'
And inside of application.html.slim:
title
= "App Name: #{t("#{controller_name.underscore}.title")}"

There's a simple way to manipulate layout variables (title, description, etc.):
# app/views/application.html.erb
<title>
<%= content_for :title || 'App default title' %>
</title>
# app/views/posts/index.html.erb
<%= content_for :title, 'List of posts' %>
And other pages will have App default title value for their titles

In application layout:
# app/views/layouts/application.html.erb
<title><%= (yield :title) || 'General title' %></title>
then in each view where you want a specific title:
<% content_for :title, 'Specific title' %>

There are already some good answers, but I'll add my simple approach. Add this to layouts/application.html
- if content_for?(:title)
-title = "My site | #{content_for(:title)}"
-else
-title = "My site | #{controller_name.titleize}"
You automagically get a nice names on all your views like "My site | Posts" -- or whatever the controller happens to be.
Of course, you can optionally set a title on a view by adding:
- content_for(:title, 'About')
and get a title like "My site | About".

Related

trying to use a news API with rails application

I'm trying to get information from newsapi. I've used the basic structure i found elsewhere for another api to start with but i'm very new to this and not sure what is wrong/how to fix etc. all i'm trying to do is display the titles of the articles on my index page. At the moment, everything displays on the page, like title, author etc as an array but i just want to narrow things down and the syntax for doing so in the view. i've changed my api key to '?' for the time being(i know it should be in the .env file).ive looked at a lot of docs but i cant seem to find an answer. apologies if
this is a broad question.
class TestsController < ApplicationController
require "open-uri"
def index
url = 'https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=????????????????????????'
article_serialized = open(url).read
#articles = JSON.parse(article_serialized)
end
end
<% #articles.each do |article| %>
<%= article[1] %>
<% end %>
This should do it
<% #articles["articles"].each do |article| %>
<%= article["title"] %>
<% end %>
Edit : This is what my ruby script looks like that I used for testing
require 'json'
file = File.read 'output.json'
data = JSON.parse(file)
data["articles"].each do |item|
print item["title"]
end

how to render partial on everything except a certain action

I have a _header.html.erb partial which is where I put my navbar
on my launch page I don't want to display the navbar.
this is the body of application.html.erb
<body>
<%= render 'layouts/header' %>
<div id="container">
<%= yield %>
</div>
</body>
How do I render it on every action except specific actions on specific controllers?
Replace your render with this:
<%= render 'layouts/header' unless #disable_nav %>
Then you can simply set disable_nav to true in any controller action you like:
def landing_page
#disable_nav = true
end
As a before_filter, which I'd encourage over the above:
application_controller.rb
def disable_nav
#disable_nav = true
end
my_controller
before_filter :disable_nav, only: [:landing_page]
You can put that logic in your stylesheets, in your controller or in your views (this last one, only for whole controllers).
Stylesheets
If you want to add the logic in your stylesheets, first add to your body tag the following classes:
<body class="<%= "#{controller.controller_name} #{controller.action_name}" %>">
Then, in your css, add something like this:
body.controller.action .navbar {
display: none;
}
Controller
To add this logic to your controller, add a before filter to your application controller:
class ApplicationController < ActionController::Base
before_filter :show_navbar
protected
def show_navbar
#show_navbar = true
end
end
Then, if you don't want to show the navbar in CarsController, do this:
class CarsController < ApplicationController
skip_before_filter :show_navbar, only: [list, of, actions]
end
where [list, of, actions] are the actions you don't want to show the navbar in.
Finally, change you layout to look like this:
<% if #show_navbar -%>
<%= render 'layouts/header' %>
<% end -%
Views
If you want to disable the header for whole controllers, first, move the header to app/views/application/ and change your render to:
<%= render partial: 'header' %>
Finally, in those controllers without navbar, add an empty _header.html.erb to app/views/controller_name.
For this option to work, you need at least Rails 3.1
I would set a different layout for those specific actions on specific controllers.

Rendered partial not receiving params

I'm trying to implement an 'edit' link that brings up a form to change a displayed attribute on a page.
My layout has:
<div id="company_info">
<%= yield :company_info %>
</div>
<div id="edit_company_info">
</div>
My view has:
<%= content_for :company_info do %>
<%= render 'company_info' %>
<%= link_to "Edit", 'company_info_form', :class => 'btn btn-mini', :method => :get, :remote => true %>
My controller has:
def company_info_form
#company = Company.get(params[:id])
respond_to do |format|
format.js
end
end
My company_info_form.js.erb file has:
$('#edit_company_info').html("<%= escape_javascript(render "company_info_form") %>");
Upon clicking the link, my server shows:
Started GET "/companies/company_info_form" for 127.0.0.1 at 2012-03-12 20:19:13 -0700
Processing by CompaniesController#show as JS
Parameters: {"id"=>"company_info_form"}
Completed 500 Internal Server Error in 1ms
RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id):
app/controllers/companies_controller.rb:9:in `show'
So I think this is a routing issue-- but I have no idea how to fix it. How do I get the company_id param that is on my current page to be recognized by the partial I'm loading as well?
I'm on /companies/1, but the link is to companies/company_info_form, losing the "company_id = 1" param.
Yes, the issue is with your routes and with your link as you have pointed out.
The first issue can be ascertained as it says Processing by CompaniesController#show as JS. So, its actually going to companies#show where it tries to find a company based on id. But, since no correct id is passed, it errors out.
The second issue is because your link is to companies/company_info_form, as you pointed out, since you have used 'company_info_form' as the path in your link for edit. And you haven't passed current company to the link either.
Since you haven't posted your routes file, which you should have, since you have identified a potential problem with routes , I'll present my own.
In your routes :
resources :companies do
member do
get 'company_info_form'
end
end
That will provide you with
company_info_form_company GET /companies/:id/company_info_form(.:format) companies#company_info_form
Then you can provide the link as :
<%= link_to "Edit", company_info_form_company_path(#company) %>

Rails 3 show text field unless it has just "#"

In my Rails 3 web app, I have a Twitter text field in one of the forms and on the user page it displays it.
<%= f.label :twitter, "Twitter Username" %>
<%= f.text_field :twitter, :value => "#" %>
And on the user page:
<% if #user.twitter? %>
<div class="twitter"><%= #user.twitter %></div>
<% end %>
The problem is, when a user doesn't enter their Twitter username into the field, it keeps # in the field and displays it on the user page. Because of this I would like to make it so if it just has # then it doesn't display it.
Looks like the # value gets persisted into the database if the user doesn't specify a twitter name, right? Are you sure you want that?
You could, in the controller, when saving the user, do something like:
user.twitter = params[:user][:twitter] unless params[:user][:twitter] == "#"
This will ensure that the User#twitter field only gets set if something is specified.
But to answer your question specifically, you can do something like this in the view:
<%= #user.twitter == "#" ? "(not provided)" : #user.twitter %>

Rails 3 Apply CSS class if path matches root:to path

I am very new to ROR and I love it so far as I develop my first app. I have a question related to my application template as I apply formatting to the nav menu.
Is it possible to check if a url path matches the root:to path set in config.rb? I have a helper method that returns the string "current" which adds the css class style to highlight the selected menu item. The helper method works fine as long as I'm not at the homepage. When I my url is www.localhost:3000/ the css current class is not applied to the Products link since the request_uri = "/" which doesn't equal "/products". I would like the css class "current" applied to the Products menu item when I'm on the homepage.
Is there any conditional logic I can use to get the root:to path and check if it matches the is_current's parameter path?
Here's my code:
routes.rb root:to setto point to the products index view
root :to => 'products#index'
application.html.erb
<%= link_to 'Products', products_path, :class => is_current(products_path) %>
<%= link_to 'Reports', reports_path , :class => is_current(reports_path) %>
application_helper.rb
def is_current(path)
if request.request_uri == path
return 'current'
end
end
Any help would be greatly appreciated.
Thanks,
bkasen
Would this work for you?
if current_page? root_path
for more info: http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-current_page%3F
If I read correctly, you want "onlink" css applied? so that when the user is on the home page, the home icon is a different color or something. If so then apply this in your header partial or where ever:
<li><%= link_to_unless_current "Home", root_path, :class => "navLinks" do link_to "Home", root_path, :class => "navLinks", :id => "onlink" end %></li>
I know this is an old question, but it may prove useful to someone else :)