Print a partial in rails - ruby-on-rails

I have a page in rails that has several partials rendered in it. I want many of those partials to have a link which will allow the user to print them. Currently, I can only get the print link to print the whole page rather than just the partial.
Is there a way to do this, or will I need the user to load a whole page before printing?
Edit:
I would like to have each partial have its own individual printing link. There are two many link_to lines I've tried using.
<%= link_to 'print ingredients', :partial => 'table_ingredients', :onclick => 'window.print();return false;' %>
The line above doesn't do anything when clicked.
<%= link_to 'print ingredients', 'table_ingredients', :onclick => 'window.print();return false;' %>
The line above prints the whole page.
I was lead to believe that the second argument for link_to was the page that should be printed.

I do it this way:
In my view I have a link like this:
<%= link_to 'Show Current Inventory Levels', parts_inventory_levels_path, :target => '_blank'%>
The :target => '_blank' causes it to open in a new tab/window
The parts_inventory_levels_path is in the routes.rb as:
get 'parts/inventory_levels' => 'parts#inventory_levels'
So it's going to the parts controller and calling the inventory_levels action which is:
def inventory_levels
#parts = Part.all.order(:name)
render 'inventory_levels', layout: "print_table"
end
Here's the key part, layout: "print_table". I have a layout file in my app/views/layout/ folder called print_table.html.erb:
<head>
<%= stylesheet_link_tag 'print', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
<%= yield(:head) %>
</head>
<body>
<%= yield %>
</body>
So the data from my controller action calls render on inventory_levels.html.erb:
<%= link_to_function('Print this Page', 'javascript:print()') %>
<br>
<table id="parts_table" class="table pretty" border='1'>
<thead>
<tr>
<th class="sortable">Name</th>
<th class="sortable">Sku</th>
...table omitted for brevity
Note the first line, it calls the javascript:print() function to print the page. The reason I render a separate page is I want to format that page in a very simple way that is better suited to printing. The nice thing is I am still able to use the table_sorter javascript to sort the table before I print it.
"I was lead to believe that the second argument for link_to was the page that should be printed." That is incorrect. The second part of the link_to is the path or url. Rails is interpreting your table_ingredients as
print ingredients
I don't know your controller name so I had to use a placeholder.
I could help you write the actual code but you should just be able to use what I have here applied to your code. But if you need more help please post your controller, and any applicable routes. You can probably reduce repetitive code by passing the same controller a value as to which partial you want to render (I am rendering a whole new page but the partial should also work). Also there is probably away to use AJAX.

Related

Pass parameter of selected line to another Ruby view

I am a beginner in ruby. I have a table in a view, that when I click on the line / item it should pick up the ID of the selected line and move to the other view that will be triggered, I am 3 days searching on and I can not implement.
The view that should take the ID or another parameter so that in the other I can treat the select to bring more detailed information >>:
<td>
<%= link_to pedido.id, detalhes_backoffice_pedidos_path(:pedido_id =>
pedido.id) , :onclick=>"window.open(this.href,'create_company',
'height=600,
width=600');return false;" %>
</td>
The view ("popup") that is called when clicked on the request id. Obs.:Tried in countless ways, and at the moment she is like this ... >>>>
<div class='container-fluid'>
<div style='display: block;' class="col-xs-6 esquerdo ">
<label>Num.pedido<%= pedido.id %></label> <br>
<label>nome</label> <br>
<label>telefone</label> <br>
</div>
Controller>>
class Backoffice::PedidosController < BackofficeController
.....
def detalhes
render :layout => "application"
#pedido = params[:pedido_id]
end
I am totally lost, after trying so much .... If you can pass some example link for study, it will be very useful too !!
It has become clear that you just need to use AJAX to show the selected pedido details on the page. Rails has an easy way to do this.
First put in a table with a div below it for displaying the pedido info. Each row in the table has a link to the controller action that will do the AJAX. Use remote: true to make the link AJAX, so the user is not taken to another page.
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'More info on this Pedido!' fetch_info_pedidos_path(pedido), remote: true %></td>
</tr>
<% end %>
</tbody>
</table>
<div id="pedido-info"></div>
Make the route for the action in the pedido controller. This is in routes.rb
resources :pedidos do
get :fetch_info, on: :member
end
This should create a path that looks like /pedidos/:id/fetch_info with the name fetch_info_pedidos
The link in the table will make a js format request along this route so the controller action must be ready to handle that. The pedido id will come as a parameter called :id
def fetch_info
#pedido = Pedido.find params[:id]
respond_to :js
end
Since it responds to a js format request it will respond with js content, not html - that means we need to have a js file as the view, but before we make that let's make a partial for displaying pedido info. This can be dropped into any view using the render method. It will be in app/views/pedidos/_pedido.html.erb (you have to use an underscore at the start of the file name to show it is a partial) You can put any content in here you like, using the pedido variable to refer to the pedido. Here's an example:
<h2>Pedido!</2>
<p>number: <%= pedido.id %></p>
<p>nom: <%= pedido.nom %></p>
<p>telefone: <%= pedido.fone%></p>
Finally let's make the js that gets passed back to the browser. This will be an erb file like other views. It will just put the _pedido partial as the content to the div under the table. app/views/pedidos/fetch_data.js.erb
$('#pedido-info').html("<%= j render #pedido %>");
That's all you need. The j here escapes the output of the render method so that it plays nicely inside a javascript string.
There's a bit of Rails magic happening here, which I will explain, because, as you would learn at any wizard training school: "don't use any magic you don't completely understand"
The render method expects the name of a partial to render, and optionally some local variables to pass. If it's given only an ActiveRecord object, it will look for the partial that matches the class name of the object (Pedido goes to _pedido.html.erb) and it passes the object as a local variable also with matching name. so render #pedido gets translated to render partial: 'pedido', locals: {pedido: #pedido}
I haven't tried any of the code in this answer, I just wrote it off the top of my head, so you may have to jiggle it a bit to get it to work.
here's a link to a page you might have come across if you had simply Googled how to do this. It says essentially the same as what I have said here, except his AJAX brings in a whole collection of objects, not just one at a time.
I may have misunderstood the question, but it seems to me you just need to link to the detalhes action for each pedido in the table.
here is the table:
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'Detalhes this Pedido!' detalhes_path(pedido) %></td>
<td>More table data related to this pedido</td>
</tr>
<% end %>
</tbody>
</table>
and in the routes you would have something like this:
resources :pedidos do
get :detalhes, on: :member, as: 'detalhes'
end

DRY view for sidebar

In my quest to keep my application views as DRY as possible I've encountered a little snag. My appliation.html.erb incorporates a static sidebar menu. Each of my main controllers incorporates a secondary sidebar menu (essentially a submenu). I can take the code that renders the menu out of application.html.erb and put it in each of my views and change the secondary sidebar there, but this produces a lot repetition in my views.
I saw this SO post and looked at this page, but I was unable to get either idea to work. I was thinking that I could put something like:
<% provide(:submenu, 'layouts/sidebars/sidebar_customers_contacts') %>
at the top of each view and use that to render the associated partial by doing
<% content_for(:submenu) do %>
<%= render :partial => :submenu %>
<% end %>
from the application.html.erb but of course that didn't work.
This is my current application.html.erb:
<div class="side">
<%= render 'layouts/sidebar' %>
<%= render 'layouts/sidebars/sidebar_dashboard' %><!-- this needs to load a sidebar based on the controller that calls it. Each view of the controller will get the same sidebar. -->
</div>
<div class="main-content">
<%= yield %>
</div>
I feel like I'm making this more difficult than it really is. Is there a simple way to do this?
Rails provides a helper called controller_name which you can read more about here.
Assuming you adhere to your own naming conventions, this should work as-is. If you decide some controllers don't get a sidebar, you may need to throw in some conditionals...
application.html.erb
<div class="side">
<%= render "layouts/sidebar" %>
<%= render "layouts/sidebars/#{ controller_name }" %>
</div>
<div class="main-content">
<%= yield %>
</div>
EDIT
Sorry, my mistake was using single quotes instead of double-quotes. You cannot use #{string interpolation} within single quotes. Source

I created a file in my new rails app and when I run the http://localhost page I get a Missing Template error message

This is the error I'm getting:
ActionView::MissingTemplate in Posts#index
Missing partial text_posts/_text_post with {:locale=>[:en], :formats=>[:html],...
Extracted source (around line #5):
3 </div>
4
5 <%= render #posts %>
Here's the code in the file app/views/posts/index.html.erb
<div class="page-header">
<h1>Home</h1>
</div>
<%= render #posts %>
I'm following along the 'Rails Crash Course' book and this is one of the steps to create a social network. I don't know the reason for the error.
I am assuming that in your posts_controller.rb file you have specified the following:
def index
#posts = Post.all
end
The reason why you are getting this error is because Rails is trying to display a partial for the variable #posts. What is implicit here, is that Rails is looking for a file named _post.html.erb in the folder app/views/posts/ and not finding anything. To fix this, you will have to manually create the file in that directory (Note that all partials begin with an underscore).
Now, if you are wondering what you should put in this partial, first you should know what <%= render #posts %> is doing. When it goes to the partial, it is iterating over all your posts and for each of them, it is going to do something. So your partial may look something like this:
<p>
<%= link_to post.title, post_path(post.id) %>
</p>
<p>
<%= link_to "Edit", edit_post_path %>
</p>
<p>
<%= link_to "Delete", post_path(post.id), method: :delete %>
</p>
Just know that what is implicit here, is that we already have a #posts.each do |post| given for us, so you only have to define whatever content you wish to display for each individual post.
Hope this helps!!
As you're using <%= render #posts %>, i'm am sure this will call the partial file with leading _ symbol on same directory. Please ensure you have already file with the name _posts.html.erb. IF you want to pass the value into partial, here i give you simple illustration :
Assume you have this in customer_controller :
def show
#customer= Customer.find(params[:id])
end
Then it instance will available on show.html.erb :
<p>Item: <%= #customer.name%></p>
These instance variables are available in layouts and partials as well, instead pass variables to partials as locals like:
// here is the same concept with your problem
// render "cust_name" find the filename leading with underscore
<%= render "cust_name", name: #customer.name%>
Above line of code will call the file with name _cust_name.html.erb that contains :
<h1><%= name %></h1>
Hope this helped.

Ruby on Rails partial not rendering properly

I have an Opportunity model and a User model. On my Opportunity index page, I have a table that lists all of the Users. When I click "Show" next to Users, the page that renders is a blank page, whereas it should say "test test test". Here is my code:
views/opportunities/index.html.erb:
<td><%= link_to 'Show', user %></td>
views/users/show.html.erb:
<% render #user %>
views/users/_user.html.erb:
test test test test
Please help!! Thanks!!
<% render #user %> will not display any result, use <%= render #user %> to display the result of the evaluated code.
Executes the ruby code within the brackets.
<% %>
Prints something into erb file.
<%= %>
Avoids line break after expression.
<% -%>
Comments out code within brackets; not sent to client (as opposed to HTML comments).
<%# %>

Render rails partial multiple times on same page

I have a partial that I'm rendering twice on the same page, but in two different locations (one is shown during standard layout, one is shown during mobile/tablet layout).
The partial is rendered exactly the same in both places, so I'd like to speed it up by storing it as a variable if possible; the partial makes an API call each time, and the 2nd call is completely unnecessary since it's a duplicate of the first API call.
Is there any way to store the HTML from the returned partial as a variable and then use that for both renders?
Edit: I'm hoping to do this without caching, as it is a very simple need and I'm looking to keep the codebase lean and readable. Is it possible to store the partial as a string variable and then reference that twice?
<% content_for :example do %>
<%= render :your_partial %>
<%end%>
then call <%= yield :example %> or <%= content_for :example %> wherever you want your partial called.
One option would be to use fragment caching. After you wrap the partial with a cache block, the second call should show the cached version of the first. For example:
<% cache do %>
<%= render(:partial => 'my_partial') %>
<% end %>
... later in the same view ...
<% cache do %>
<%= render(:partial => 'my_partial') %>
<% end %>
To store the result of the render to a string, you could try the render_to_string method of AbstractController. The arguments are the same as for render.
partial_string = render_to_string(:partial => 'my_partial')
I'm adding an answer to this old question because it topped Google for a search I just made.
There's another way to do this now (for quite a while), the capture helper.
<% reuse_my_partial = capture do %>
<%= render partial: "your_partial" %>
<% end %>
<div class="visible-on-desktop"
<%= reuse_my_partial %>
</div>
<div class="visible-on-mobile"
<%= reuse_my_partial %>
</div>
This is simpler and slightly safer than using content_for because there is no global storage involved that something else might modify.
The rails docs linked to use instance #vars instead of local vars because they want it to be available to their layout template. That's a detail you do not need to worry about, because you're using it in the same template file.

Resources