rails add css class if the page has a 404 status - ruby-on-rails

Is there a way in Rails to add a class to a html tag if the current page rendered a 404 error.
On a controller of mine, if a user visits the wrong website it renders a file in the public error with a 404 error like this
else
render file: 'public/error', status: 404, formats: [:html]
end
I want to add a class to my footer, hidden, to hide the footer if this page is rendered. I've tried this with no luck (but it was more of a guess)
<%= "hidden" if current_page?(status: 404) %>
Any suggestions??

You could make it more generic and set an #variable to tell the footer to hide. So if later on you want a 500 page without footer you can use the same trick.
controller
else
#hide_footer = true
render file: 'public/error', status: 404, formats: [:html]
end
view
<%= "hidden" if #hide_footer %>
And you don't need to change anything else.

You could just render a separate layout for your error files
else
render :template => "shared/404", :layout => 'errorlayout', :status => 404
end
You might want to have a look at these questions and answers as well:
Dynamic error pages in Rails 3
how to remove header and footer from some of the pages in ruby on rails
How to hide footer layout on a particular page? - This is basically Ismael Abreu suggestion and is probably the easiest.

Related

Rails not rendering view in custom page

I am trying to render contents of user_details\index.html.erb in my custom page home.html
here is my directory structure
apps
|
views
├───co_owners
├───layouts
├───pages
├───shared
└───user_details
the home.html.erb page is pages directory... and index.html.erb pages is in user_details directory
i am using
<%= render :partial => 'user_details' %> to render it on my home page... but i am getting error ActionView::MissingTemplate in Pages#home
how can i do this?
As an answer in a previous your question
It is not a partial (starts with underscore), so you need render
template. You also need the full path of the template, from the view
directory:
<%= render template: 'user_details/index' %>
I suggest you read Layouts and Rendering in Rails

Rendering plain text in rails 4

I am using render :plain => "some text" and It's working fine.
But as the text gets longer, I wish to place the text in an erb file (e.g. sometext.text.erb) and render the text.erb.
I have a sometext.text.erb in the view folder. But render method doesn't seem to detect it.
How are you rendering plain text? Thanks!
Update: Using the answer below works. So the solution is to set render layout to false. And proceed to use sometext.html.erb instead of sometext.text.erb
Just don't render the layout:
class MyController < ApplicationController
def your_action
render layout: false
end
end
This will follow the convention to find your view, so it will expect your view to be at app/views/my_controller/your_action.html.erb

Render :layout is searching for partial instead of layout

I understand this is a bad idea, but from what I've seen in ApplicationControllers, using:
render :layout => "something" ...
Should render using a layout located at views/layouts/something.html.erb
However, when I am making this call from inside of a view, it errors out with:
Missing partial my_controller_name/something with ...
Searched in:
* "{path here}/app/views"
Which seems to me its looking for a partial, instead of a layout as I specified. Does anyone know what is going on with that?
A sufficient example small enough to reproduce it:
<%= render :layout => 'something' do %>
<div>Hello</div>
<% end %>
This is all under Rails vs 4.0.2
render works differently in controllers than it does in views. In controllers, it's primarily for rendering action templates, while in views, it's primarily for rendering partial templates. When you want to render a specific layout for an action, you have a few options, but all of them are in the controller.
If you want every action in a particular controller to use that layout, you can either specify layout 'something' in that controller (usually near the top) or for a ApplesController, you can create a new layout in app/views/layouts/apples.html.erb and this will automatically be used as the default layout for the ApplesController.
If you want just a single action in a controller to use that layout, you can use your render layout: 'something' inside of a controller action, where the action to render is implied to be the current action.
Links from the Rails docs:
Action Rendering
Partial Rendering
Nested Layouts

Returning: A full page, JSON, and a partial HTML snippet from Ruby on Rails Controller

I know this question has been asked in part a few other times on SO but I was curious about doing it a different way. In my Ruby on Rails app I have an action called list on my UsersController.rb controller. I want this list to respond to 3 different things
The page itself. Rending the whole page of users I specify
A JSON list of users for the page I specify
A partial view of just the rows for the page I'm specifying formatted as HTML.
Imagine a full page (header, footer, everything) with a table that has page 1 of users. When I click page 2 I want to kick off an ajax request back to the same controller action to give me just the html rows for page 2. I also want to persist my JSON API still allowing my controller to return JSON lists when asked. I imagine it looking someting like this.
class UsersController < ApplicationController
def list
respond_to do |format|
format.html # RETURNS MY VIEW
format.json # RETURNS MY JSON LIST
format.partial_html # RETURNS MY PARTIAL HTML
end
end
end
Is there anyway to accomplish this in RoR? Or am I doomed into having to create another action in my controller just to return technically the same data?
Could I make this happen by specifying my own MIME type? Should I snake in the partial as an XML return type?
Use format.js on the third line.
Put the partial html on a partial, call it app/views/users/_html_rows.html.erb.
render that partial both on the full html and on the js version.
You will have app/views/users/list.html.erb with the full html content, which will be something like this:
<html>
<body>
.....
<table id="my_table"><%= render 'users/html_rows', users: #users %></table>
</body>
</html>
You will have app/views/users/_html_rows.html.erb with:
<tbody>
<% users.each do |user| %>
<tr>
<td>user.name</td>
</tr>
</tbody>
Then you will have app/views/users/list.js.erb with:
$("#my_table tbody").html("<%= render 'users/html_rows', users: #users %>");
This probably will solve your problem.
You can add an additional mime type entry to work with respond_to. In config/initializers/mime_types.rb, add:
# htmlp means "html partial"
Mime::Type.register "text/html", :htmlp
In your controller you can now do:
def list
respond_to do |format|
format.html
format.json
format.htmlp { render layout: nil }
end
end
And create a template called list.htmlp.erb with your partial content in it.

Don't render layout when calling from Ajax

I have a rails action called index that renders the content for my page along with the layout. When I go to the /index action with a browser it works like expected. I want to be able to also render this action by calling it with Ajax, I am doing this using the following:
<%= link_to "Back", orders_path, :id => 'back_btn', :remote => true %>
<%= javascript_tag do %>
jQuery("#back_btn").bind("ajax:complete", function(et, e){
jQuery("#mybox").html(e.responseText);
});
<% end %>
When the action is called this way I would like it to render and pass the index action back, excluding the layout. How can I do this?
You should be able to add a format.js action to your controller action like so:
respond_to do |format|
format.js
format.html
format.json { render json: #foos }
Ideally, you would want to create a index.js.erb file that would build the contents of the page:
$('#foos_list').update("<%= escape_javascript(render(#foos)) %>");
If you're going to update the contents of a div, to basically update a whole page inside of a layout, then you're going to want to change it up a little bit. Inside of the format.js, you can do this:
format.js { render 'foos/index', :layout => false }
But if you're trying to go with an ajaxified front-end, may I recommend a framework for doing this, like Spine? It will go a long way in helping you build your site.
Also, using a framework like this will force you to separate your application per #Zepplock's second suggestion.
You can just detect if the request is an XML HTTP Request, then render a blank layout like so:
render layout: 'blank' if request.xhr?
You'll need to create a blank layout in app/views/layouts/blank.html.erb like this:
<%= yield %>
You need a way to let server know that there's a difference in request type. It can be done in several different ways:
Append a key value to the URL (for example layout=off) and change your controller logic to render data with no view. This is kind of a hack.
Make your controller return data via XML or JSON (controller will know what content type is being requested) then format it accordingly and present in browser. This is more preferred way since you have a clear separation between content types and is better suited for MVC architecture.
Create an API that will serve data. This will lead to separate auth logic, more code on client side, additional APi controller(s) on server etc. Most likely an overkill for your case

Resources