I have a Rails 3 application that is using the 960 grid CSS layout(s). There are a couple of different views that stretch in width and I am trying to come up with a good way to dynamically change out those classes.
For Example:
My Devise Controllers (Sessions, Passwords, etc) all use a certain class to restrict the width to 340px, while most of my other controllers use another class to restrict the width to 540px
So my 340px layout uses class names grid_6 push_5, while my 540px layout uses grid_10 push_3
Anyway to grab the accessed controller in the application_controller? My thinking is to just get the controller and have a switch statement that sets the class names in a helper_method.
Thoughts?
I was able to figure it out, thanks to this post: Determine the requested Controller in - ApplicationController
Here is how I ended up doing it (application.html.erb):
<%= render :partial => 'common/content_container', :locals => { :controller => params[:controller] } %>
content_container partial:
<% case controller
when "sessions", "passwords"
container_div_grid_number = "6"
container_div_push_number = "5"
else
container_div_grid_number = "10"
container_div_push_number = "3"
end
%>
<div class="grid_<%= container_div_grid_number %> push_<%= container_div_push_number %> ">
<div class="top_<%= container_div_grid_number %>"></div>
<div class="middle_<%= container_div_grid_number %>">
<%= yield %>
</div>
<div class="bottom_<%= container_div_grid_number %>"></div>
</div>
Rails 3.2.1: I have the following div that calls a partial
<div id="weighin">
<%= render :partial => "my_weight/weighin" %>
</div>
The partial contains a form that posts ajax (ie has :remote => true) to a controller with:
respond_to do |format|
format.js
end
The .js.erb file has a single line:
$("#weighin").html("<%= render :partial => "my_weight/weighin1" %>");
The _weighin1.html.erb partial file has a single line:
<p><%= #my_weight[1].weight %></p>
This works, in that the original div is replaced with the value of the #my_weight field - so the fundamental structure is all working ok
However, Rails will not handle any more code in the partial - if I add so much as a carriage return to the end of that one line, the server log confirms all ok, but no script gets run on the page - ie nothing changes.
The same happens if I try to put more html in the partial, but put it all in a single line - this doesnt run either.
How can I output more than a single short statement in a partial?
OK, I figured this out:
$("#weighin").html("<%= escape_javascript(render :partial => "my_weight/weighin1") %>");
escape_javascript is essential
What is confusing is that, depending on what is in the html() you are sending, this will sometimes work without escape_javascript, leading one to a false conclusion... :-)
I'm looking for a generic way to apply some external CSS frameworks in a Rails application. These frameworks typically define a set of class names which should be used for certain HTML elements.
Consider jQuery UI. To achive a consistent form style, you would to something like this:
# in a view
<% form_for #foo do |f| %>
...
<%= f.text_field :bar, :class => ['ui-widget', 'ui-widget-content', 'ui-widget-container', 'ui-corner-all'] %>
or
<%= f.text_field :bar, :class => 'ui-widget ui-widget-content ui-widget-container ui-corner-all' %>
<% end %>
Doing this for each input field is not DRY at all.
Even a helper method like
# in application_helper.rb
def jquery_ui_classes
'ui-widget ui-widget-content ui-widget-container ui-corner-all'
end
# in a view
<%= f.text_field :bar, :class => jquery_ui_classes %>
or
# in application_helper.rb
def jquery_text_field(form_builder, method, opts = {})
ui = ['ui-widget', 'ui-widget-content', 'ui-widget-container', 'ui-corner-all']
klass = [opts.delete(:class), ui].flatten.compact
form_builder.text_field method opts.merge(:class => klass)
end
# in a view
<%= jquery_text_field f, :bar %>
does not look right (or more DRY), since you still would have to touch the generated form view...
Alternative ways might now be monkey-patching the InstanceTag class or hacking into the form_for helper.
Has anyone done this before?
By the way: I would avoid using jQuery (or Javascript in general) to apply the class attributes, since JS might be disabled or blocked or even delivered with delay and cause a flickering...
Cheers,
Dominik
https://github.com/phallstrom/form_helper_css
You can't specify the classes you want, but it will add reasonable class names to all inputs to allow you to easily target them (in all browsers).
I have a link that needs to show a hidden Div on click.
For it, I am using :
<%=link_to video.title,display_path(:format=>:js,:id=>video.id),:remote=>true%>
in the controller i have:
def display
#video=Video.find(params[:id])
respond_to do |format|
format.js
end
end
and in the js.erb, i have,
$('#vid_<%=#video.id%>').fadeIn('slow');
But when i run the app, upon clicking the link, the js.erb is rendered as text.It just displays:
$('#vid_<%=#video.id%>').fadeIn('slow');
You should read
Rails Ajax: .js.erb rendered as text, not JS
for a full explaination
You are doing everything right, but you can improve your code a little
views
# use spaces to ident all this stuff and write less if it is possible:
<%= link_to video.title, [:display, video], :remote => true %>
controller
class VideosController < ApplicationController
respond_to :html, :js
...
def display
#video=Video.find(params[:id])
respond_with #video
end
...
end
display.js.erb
$('#vid_<%= #video.id %>').fadeIn('slow');
Be sure, that you have installed jQuery:
rails g jquery:install
and included it into your application layout file.
<%= javascript_include_tag :defaults %>
Ok I found the solution.I made a silly mistake.I forgot to skip prototype while creating the App.This caused trouble when i tried to use Jquery.Its all good now.
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".