rails access view name inside partial - ruby-on-rails

I have a partial that I am using in different pages. I want to conditionally hide a certain div inside the partial based on the view that is rendering it.
I was thinking about creating a page specific javascript file that would look up the div and and hide it.
But, if there was a way to retrieve the view name / page name inside the partial it would be central to the partial and would not necessitate loading the same javascript file in multiple pages.
Does anybody know a way to do this inside a partial

While #wahaj's answer would work, if you want to do what you need in a central location, you could check the controller_name and action_name variables in the partial to determine the view you're in (e.g. controller_name == "services" and action_name == "show" would let you know you're in the Show view for the Service controller)

you can get the name of the currently-rendering partial from within a Helper method with the following :
controller.view_context.view_renderer.instance_variable_get('#_partial_renderer').instance_values['path']

You could send the style parameter as a local variable to the partial, varying the parameter depending on where you're calling from. Something like:
render :partial => 'xyz', :locals => {:style => 'display:none or display:block'}
and in the partial you could do:
<div style=<%=style%>></div>

simple solution , inside your partial check if you need to show partial or not
_partial_name.html.erb
<%= content_tag :div, :style=> "display : #{show_div? ? 'block' : 'none'}" do%>
html...or other stuff
<%end%>
and then in application helper
app/helper/application_helper.rb
def show_div? #you can set name of your div like 'show_sidebar_div?'
#decide either show this div or not
action_name == 'show'
end

Related

how to pass and access data to partial view in ruby on rails?

I'm adding a new partial view in ruby on rails project and want to pass some additional data to the partial. I have code below for rendering a view . I understand this is the way to pass data (id in my case) to partial view. I'm not sure if this is the best way, as I'm new to rubyonrails. How do i access in my partial view file?
render "index" , :locals => {:id => params[:id]}
You can pass data to your view(s) using options on render, one of which is locals, or by setting instance variables which automatically propagate.
Normally what's done is something like this:
#id_param = params[:id]
Where within your view you can use #id_param wherever and whenever:
<%= #id_param %>
I've chosen #id_param for a name here instead of #id to give it a bit more context as #id on its own might prompt questions of "What ID?"
If you want to do the locals method, then:
render 'index', locals: { id: params[:id] }
Using the Ruby 1.9 hash notation for simplicity here, versus the outdated 1.8 style in your original example. This produces a local variable called id that can be used in that view, like:
<%= id %>

Render show view in a partial - Ruby on Rails

So I have a sidebar in my rails application. Basically, I have a grid full of images. When someone clicks on an image in the grid, I basically want the show view to be displayed in the sidebar. I'm clueless on how to do this.
I've tried copying and pasting the show view's html and erb into my _sidebar.html.erb partial. But I get variable errors. My partial is located in my layout folder. But I can move it if needed.
Here is an image of the application for a better idea of what I'm talking about.
Here's how to do it:
1) Include the sidebar partial in your layout:
#app/views/layouts/application.html.erb
<%= render "shared/sidebar" %>
This calls the _sidebar.html.erb partial in /app/views/shared:
2) Populate the "default" sidebar partial:
#app/views/shared/_sidebar.html.erb
...
The important thing to note here is that partials should never have #instance variables inside.
Partials have locals, which you can pass with the following command:
<%= render "shared/sidebar", locals: { variable: "value" } %>
Partials are meant to run on any part of your web application, and since #instance variables are present for a single "instance" of an object (IE #post won't be available in /users), you can ensure partials are always populated by passing local variables to them.
This is why you received errors when copying your post#show code to your sidebar partial -- the instance variables present for the show action will not be present in other parts of the app.
3) Use JS to pull image objects
When someone clicks on an image in the grid, I basically want the show view to be displayed in the sidebar.
You need to be more specific - do you really want the "show" action to appear, or do you want parts of its functionality?
Either way, you'll be best using JS & ajax to pull the data:
#app/controllers/images_controller.rb
class ImagesController < ApplicationController
layout Proc.new { |controller| !controller.request.xhr? }
end
#app/assets/javascripts/application.js
$(document).on("click", "img", function(e) {
e.preventDefault();
$.get($(this).attr("href"), function(data){
$(".sidebar .image").html(data);
});
});
This will take the rendered images#show action (without layout), and append it to your sidebar partial. This is what you asked for - I can change it if required.
Lets say that your model is called "Image".
In your "images/show.html.erb":
# This is a handy shortcut that will call the 'images/_image' partial.
# Those two lines are exactly the same.
<%= render #image %>
<%= render "images/image", image: #image %>
In your "_sidebar.html.erb":
<div id="sidebar-img"></div>
In your "images/_image.html.erb":
# Code displaying your image, don't use any global variable.
# 'image' is the name of the local variable
In your grid:
# remote: true allows you to do an AJAX call
<%= link_to image, remote: true do %>
# Something like that, I don't know your code
<%= image_tag image.url %>
<% end %>
Create "images/show.js.erb", when clicking on a 'remote :true' link it will call this file.
# set #image to Image.find(params[:id]) in your controller
$("#sidebar-img").html("<%= render #image %>");

Rails erb templating, link element visibility to action in yield?

In application.html.erb file, can I link HTML elements visibility to actions that are inside the <%= yield %> tag ?
For example if I have a header element and want to display a text there if <%= yield %> is displaying a specific action?
You can use the current_page? helper to determine if you're on a specific page (as identified with the given path parameters, etc.) and branch accordingly.
Or, if you need a more broad stroke you can use controller_name and/or action_name to get the current controller's name and the current action's name and branch accordingly.
Lastly, you can inspect params[:controller] or params[:action], which are sometimes more revealing than the above.

I want to render controller/action inside a div in Rails

Lets say I have a 300X300px block called "Statistics" or "Friends" this block requires some database objects and logical operations that traditionally should be placed inside a controller, which prepares some instance variables that will be displayed nicely in it's view/partial.
This block could be called from many pages in my website, crossing various controllers and actions.
How can I go about this problem without repeating code inside controllers, nor placing logic inside views.
A bad solution would be to place SQL queries inside views, or using iframes where a single controller/action generates the expected HTML.
Any ideas will be greatly appreciated.
I think this is the kind of thing you should do in a helper method. It might be a good idea to use locals for you partial instead of instance variables so as not to pollute the namespace of your views:
module ApplicatonHelper
def friends_block
friends = Friend.where(...)
# Assuming the 'friends_block' partial is in a directory 'app/views/shared'
render :partial => "shared/friends_block", :locals => {:friends => friends}
end
end
The friends_block partial would use the local variable:
<div id="friends_block">
<% friends.each do |s| %>
...
<% end %>
</div>
And other views would just use the helper method without having to worry about anything else:
<%= friends_block %>
Have a look at the Cells gem:
https://github.com/apotonick/cells
I'd put the block into a partial and ensure that the required instance variables for that block are loaded in a before_filter on the relevant controllers and actions.

Render a view of another controller

What I want to do is have 2 different controllers, client and test_client. The client controller is already built and I want to create a test_client controller that i can use to play around with the UI of the client and adjust it as needed. I am mainly trying to get around the validation i have built into the client and its dependence on an admin controller that loads the data.
so i want the test_client controller to load a sample data set and then render the client controller's index view so i can adjust the clients UI. That is all.
I tried this in the test_clients index method:
class TestClient
def index
render :template => 'client/index'
end
end
but i get an error because it cannot find the client partials as it is looking in the current controllers view for them...
So I have looked into this already and most people say that you should never make such a call but i think that this case is a reasonable usage...I just need to figure out how to get it to work.
You will need to adjust your view so that the path to the partial you need is in the form 'controller/partial'. In this case probably 'client/partial'. Then you can simply use render 'client/index' as before.
So say somewhere in your view you have this:
<%= render :partial => 'info' %>
You will want to change it to this:
<%= render :partial => 'client/info' %>
Convert your client controller views to partials, create empty views for all actions in test_client controller, render client partials for respective test_client views.
Example:
client view
index.html.erb to _index.html.erb
test_client view
index.html.erb
in this view, <%=render :partial => 'clients/index', :locals =>{ }%>
You could do this in a number of ways and everyone is different. One way you could do it, is by putting your finders into a presenter. Then turn some data in the index view into a partial or you can render the template with layout set to false.
Then in the client_test view you can render that index with the presenter associated with it.

Resources