Rendering Layouts without loading its inner layout in Rails - ruby-on-rails

Im trying to bring a layout in my html page by
render layout 'flatty'
thing is this loads the whole flatty layout. In flatty.html.erb it renders _header,_footer and also _sidebar.html.erb
I dont want to load _sidebar.html.erb in this particular page.
So how should i render this?

thing is this loads the whole flatty layout. In flatty.html.erb it renders _header,_footer and also _sidebar.html.erb I dont want to load _sidebar.html.erb in this particular page
Why do you want to use same layout if you have so many changes? Why not make a partial which you could render in both cases. Make a new partial, lets say _common.html.erb, render it in your flatty layout and view of the action in which you want to use it.
#flatty.html.erb
<%= render "common" %>
<%= render "sidebar" %>
#some_action_name.html.erb
<%= render "common" %>
If you still want to use same layout in both cases then you ca use rails 4 controller_name and action_name helpers in your layout and selectively render sidebar and other partials in your layout:
#flatty.html.erb
<%= if controller_name == "some_controller_name" && action_name == "some_action_name"
<%= render "sidebar" %>
<% end %>

Maybe in your controller action, you can have a flag indicating the sidebar should not be rendered. Then, in your flatty.html.erb file, check for the flag variable before you render the _sidebar.html.erb.
For example, if you have a controller action called flatty, add an instance variable, #disable_sidebar, to act as your flag.
def flatty
#disable_sidebar = true
# Your other code
render layout: 'flatty'
end
Then, in your flatty.html.erb, add a conditional before your render for your sidebar (note the ! negation in the if statement:
<% if !#disable_sidebar %>
<%= render "layouts/sidebar" %>
<% end %>
Alternatively, in your flatty.html.erb you can also check for the controller and action values in your params hash, and then don't render your sidebar if it matches that controller's action:
<% if params[:controller]!="YOUR_CONTROLLER" and !params[:action].eql? "flatty" %>
<%= render "layouts/sidebar" %>
<% end %>

Related

How to render the index view, from inside a view in ruby-on-rails

I'm trying to render a the index view inside my ruby-on-rails application. How do a I render the index view, from inside a view passing an array of things to display? Using the link_to.
I do not want to re-route to the controller, I just want to link_to a view passing it the variables it needs, how can I do this?
EDIT:
I am trying to create a page type functionality in the index of my article model. So I have around 400 articles for example, and when the index action in the article controller is called, it of course renders the index view which is calling a partial for each article in the '#articles array' passed on by article controller's index action.
So in the view, I'm trying to do something like:
<% count = 0 %>
<% #articles.each do |article| %>
<% if count <10 %>
<%= render partial: 'index_articles', locals: {article: article} %>
<% count = count + 1 %>
<% end %>
<% end %>
<% #articles = #articles.drop(10) %>
<% if #articles.any? %>
<%= link_to "Next", 'articles', locals: {#articles => #articles} %>
<% end %>
Thank you in advanced for all of your help.
You'll need to use the render command, probably with a partial:
<%= render "controller/index", collection: ["your", "array"], as: :object_name %>
You will have to call a controller action to generate this. You cannot simply load it on your screen, unless it was preloaded inside your javascript for something:
#View
<%= link_to "Index", controllers_path(ids: ["1","2"]), remote: true %>
#app/controllers/your_controller.rb
class YourController < ApplicationController
def index
#posts = request.xhr? Post.find(params[:ids]) : Post.all
respond_to do |format|
format.js #-> app/views/controller/index.js.erb
format.html
end
end
end
#app/views/controller/index.js.erb
$(".element").html("<%=j render 'index' %>");
There are several issues with this approach...
Flow
First of all, your flow of your app should be as structured as possible.
In short, if you're calling the index view inside another action, it's not the index view any more.
What you should look at is how to use a partial in your app:
#app/controller/views/_partial.html.erb
<%= post.title %>
This way, you can adapt your index view and your other page to use the partial in their respective action layouts:
#app/controller/views/index.html.erb
<%= render "partial", collection: #posts, as: :post %>
This will allow you to "reuse" code much in the way you want. This will be much more appropriate than trying to invoke other action/views.
-
Resources
Secondly, you'll want to look at how your app functions.
Your index view is meant to show all the items for a particular object. Whilst you're free to change this as you want, the fact remains that you have to keep some structure.
You should read up on the routes for your actions, and how they're meant to work in your application. This will give you some perspective on the resourceful nature of Rails routes, and how you'll have to call specific routes with specific actions.
Your problem is probably that the file needs to be named _index.html.erb. You can have another file named index.html.erb which just renders _index.html.erb.
If you need a full guide on using AJAX, look up the railscast. If you're not using AJAX and you just want to render it, then you don't use link_to. You just do <%= render :index %>.

Spree - Render Partial if

I'm trying to render a partial on home page. Code is a follows:
<%= render :partial => 'spree/shared/slider' %>
The thing is I want it to render/show the partial only if I'm on the home page .To summaries for a particular page/pages only.
Can anyone help me with this? Thank you.
You can use a conditional for deciding whether the partial should be rendered:
<%= render :partial => 'spree/shared/slider' if #slider %>
The condition could be an instance variable (e.g. #slider) which can be set from the view (when not set, it remains nil by default):
<% #slider = true %>
Now the partial will only be rendered if #slider has been explicitly set to true in the view or in the controller.

On rendering from controller, current_page method does not seem to work

I have a navigation bar included in application.html.erb. Because for some pages, such as the signup page, I need to place additional code inside the navigation bar, I have excluded those pages for showing the navigation bar through application.html.erb and instead included it in their respective view pages. See code below.
A problem arises when invalid data is entered in the signup form. The controller method then renders new. However, application.html.erb then doesn't seem to recognize that the current_page is still signup_path, therefore not applying the exception for not showing the navigation bar on that page. As a result when it renders new, the navigation bar is shown twice: once by order of application.html.erb and once by order of the view page itself.
Why, when rendering new on an invalid form entry, does it not see that it's still on signup_path? How should I adjust my code so that it does not show the navigation bar twice in that situation? Is there perhaps a way of including <%= yield special code if any %> in application.html.erb and <% special_code %> <% end special_code %> in the view page that passes this special code to application.html.erb?
In application.html.erb I have:
<% unless current_page?(signup_path) %>
<nav class="banner">
<%= render partial: "shared/header" %>
</nav>
<% end %>
In the view of my signup page:
<nav class="banner">
<%= render partial: "shared/header" %>
Additional code that needs to be within 'nav' for this page
</nav>
Controller method:
def create
#user = User.new(user_params)
if #stakeholder.save
flash[:success] = "A confirmation email has been sent to you."
redirect_to root_url
else
render 'new' ###This is where it goes wrong!
end
end
You can use content_for and yields to create a default in your layout which views can override.
# layouts/application.html.erb:
<% if content_for?(:banner) %>
<%= yield(:banner) %>
<% else %>
<div id="banner">
<h1>This is the default...</h1>
</div>
<% end %>
/users/signup.html.erb:
<%- content_for :banner, flush: true do -%>
<!-- move along, nothing to see here -->
<%- end -%>
The advantage here is that you don't end up turning your layouts into a birds nest of conditionals. You can easily just inject whatever you want into the layout from views.
The cons are that you have to use a stupid hack with a HTML comment to override the block to display nothing since content_for? trims the block. content_for does not play nice with fragment catching either.
addded
I didn't touch on this before unless current_page?(signup_path) does not work as you expect since render 'new' does not magically move you to the new action. In fact the current_path is /users since the form POST's to that url.
It just tells rails to find a template named 'new' and render it.
A corrected version would be:
<% unless controller_name == 'users' && ['new', 'create'].include?( action_name) %>
<nav class="banner">
<%= render partial: "shared/header" %>
</nav>
<% end %>
You are completely right. This is where it goes wrong
render 'new' ###This is where it goes wrong!
Here's what happens
user requests a new action, which renders the new template
user submits the form, thus requesting the create action in your controller
inside your create action you render your new template instead of create when validation fails
So basically user is no longer on the new page, but on the create page with a view rendered from new.
The easiest solution would be to change expectation for the header to both new and create actions, since you redirect on success, so you won't use it otherwise.

Rails Partials For Resources

I have a resource called Exercises in my application. I currently have a partial called _exercise.html.erb that I use to render them. I have an outlying case where I'd like to render them in a much different way. Can I make another partial for exercises that has this other format and still be able to use <%= render #exercises %>?
If not what is the best approach? Should I out a variable in the controller that tells the partial which layout to use, this would have both layout in one file and one if to decide. Or is there some better way?
If you'd like to use business logic to determine when to show what partial for your #exercises collection you should use the to_partial_path method in the Exercise model to define that. See #4 in this post: http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/
Or, if this is more of a view-related decision (i.e. one view will always use the regular _exercises.html.erb and another view would always use e.g. _alternate_exercises.html.erb) then you can specify as such:
<%= render partial: 'alternate_exercises', collection: #exercises, as: :exercise %>
This will render the _alternate_exercises.html.erb partial once for each item in #execrises passing the item in to the partial via a local_assign called exercise.
In this case, I suppose you have two options:
1) Put the conditional code inside of _exercises.html.erb
eg.
<% if #exercise.meets_some_condition %>
you see this stuff
<% else %>
you see other stuff
<% end %>
This way, you can still make use of <%= render #exercises %>
2) Otherwise, your other option is to have separate partials and render them outside.
eg.
<% #exercises.each do |exercise| %>
<% if exercise.meets_some_condition %>
<%= render "exercises/some_condition_exercise" %>
<% else %>
<%= render "exercises/exercise" %>
<% end %>
<% end %>
This is the best approach for rendering partial. You can wrap that partial with if else statement in your code. Here is my example
rendering with form called _victim.html.erb
<%= render :partial => "victim", :locals => {:f => f }%>
rendering without form
<%= render :partial => "victim"%>

Avoiding repetitive "content_for" in views

I have a submenu placed in my layout wich differs from controller to controller, but not between each controllers method views. What I am currently doing is the following:
<% content_for( :submenu ) do %>
<%= render :partial => 'submenus/correct_submenu' %>
<% end %>
In every view for a method
My applications layout then has this in it
<%= yield :submenu %>
However, this feels kind of repetitive, doing it for each view. Is there some way to do this per controller?
My suggest is to have a convention for this, so if you have a ProductsController then the submenu would be submenus/products_menu. This way you can write a helper that looks like:
def render_submenu
content_for(:submenu) { render :partial => "submenus/#{controller.controller_name}_menu" }
end
You can then call this by doing:
<%= render_submenu %>
You could then make this the default content_for the submenus and only specify the content if it needs to be different.
I hope this helps!
Use nested layouts to nest a specific controller's layout under the application layout, by creating a file like so:
# app/view/layouts/<controller_name>.html.erb
<% content_for( :submenu ) do %>
<%= render :partial => 'submenus/correct_submenu' %>
<% end %>
<%= render template: "layouts/application" %>
With this method, you don't have to modify a bunch of view files.

Resources