Rails partial from different controller in a Bootstrap tab - ruby-on-rails

I have a Home page with 2 Bootstap tabs. I'm having problems with the 2nd tab. I'm trying to render a list of workorders. For that list I'm using dataTables and ajax.
My issue is that workorders/index7.html.erb works fine as a stand alone page. But, I want to use it in a Bootstrap tab on the Home page.
For all my other Bootstrap tab lists, I'm using partials from within the same controller. But, in this case, I need to use a view from the Workorder controller not the Home controller.
This is the code I'm trying in the Home view:
<div class="tab-pane" id="tab2">
<%= render "workorders/index7" %>
</div>
That code gives me:
Missing partial workorders/index7
WHY? If I change the file name to _index7.html.erb the code won't execute to get the json.
But, because it's a partial, starting with _, the connection to the Workorder controller code for index7 doesn't work. I also tried _index7 in the Workorder controller.
The Workorder controller has this code:
def index7
#workorders = Workorder.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: Workorders3Datatable.new(view_context) }
end
end
That code uses a file called workorders3_datatable.rb to get the data via ajax and format it for dataTables.
QUESTIONS:
1) Do I have to use a partial in the Home tab? Or is there a way to render a file called workorders/index7.html.erb in the tab?
2) Why does index7.html.erb use the controller code for index7, yet the partial _index7.html.erb won't use code if I call it _index7 in the controller?
3) I read this "Render will just render the view, it won't run the action associated with it." - is that true?
Thanks for your help - I know this is confusing.
Reddirt
UPDATE 1
The view runs great as workorders/index7 - but, if I change it to a partial and put it in a tab = workorders/_index7 - the controller code for index7 doesn't seem to execute.

1) Do I have to use a partial in the Home tab? Or is there a way to view a file called workorders/index7.html in the tab?
If you want to follow this approach. From Home controller pass the collection (#workorders = Workorder.all)
Then in the home view pass it to the workorders/index7 as locals
<div class="tab-pane" id="tab2">
<%= render "workorders/index7" locals: {workorders: #workorders} %>
</div>
This will make it available to workorders/index7 do remember to change the variable to a local variable workorders.

You need to include :partial in the view for your Home page:
<%= render :partial => "workorders/index7" %>
The app/views/workorders folder will need a file called _index7.html.erb. To accomplish this from your current setup, you can move the contents of index7.html.erb into this partial, and then use:
<%= render :partial => "index7" %>
in the original index7.html.erb. That way you can render that as a whole page and within your Home page as a partial.

Related

How to pass object to partial using controller?

I've been trying to pass my Product object to my rendered partial but no matter what I try it doesn't work. The home page has a quick view button that pops a modal (the partial) and I want to pass the correct product to it.
Route
get 'shop-product-ajax-page', to: "pages#shop_product_ajax_page"
Home Page (shortened to only the link for brevity)
<% #products.each do |product| %>
<%= link_to "Quick View", shop_product_ajax_page_path, :data => {:lightbox => 'ajax'} %>
<% end %>
Controller Action
def shop_product_ajax_page
render :partial => 'pages/shop_product_ajax_page', :layout => false
end
Right now, the button works and displays the HTML in the modal. I want to be able to populate the correct product information for whatever Quick View product is selected.
The problem is that the link is making a completely separate AJAX request, it's hitting the server separately, so the Ruby context you expect (variables etc) isn't available in that new request.
Two choices:
Don't make an AJAX request but render the lightbox as part of the page. You could hide it using display: none or similar, then use Javascript to display it when the link is clicked.
Make the request the way you currently are, but pass in the same parameters that your current controller action is using to get #products and in shop_product_ajax_page do the same thing to hit the database and get the products.
The second choice might be easier without messing with JS. It would be something like:
def shop_product_ajax_page
#products = get_products_from_params(params)
render :partial => 'pages/shop_product_ajax_page', :layout => false
end
private
def get_products_from_params(params)
Product.find(params["product_ids"]) # or whatever you're currently doing
end

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 %>");

Render html.erb (not partial) in other html.erb

I'm quite new to Rails and trying to make app with Foundation framework. The problem is with modal window.
I have an index.html.erb file in views/users folder, generated by scaffold.
Also there is a new.html.erb file in the same folder.
I want to open ../users/new link in modal window on index page.
I used examples in Reveal (Foundation Documentation), put new.html.erb file content in:
<div id="myModal" class="reveal-modal">
.
.
</div>
Also, add to New User link "href" attribute.
<%= link_to 'New User', new_user_path, 'data-reveal-id' => 'myModal' %>
as was described here.
Now I need to render new.html.erb in index.html.erb, cause I need this code just before /body tag, as described in Foundation Docs.
I've tried to render it as partial, but it doesn't work.
Is there any way to do it, without double new.html.erb as _new.html.erb and inserting it as partial in index.html.erb?
I don't think, that RoR with all there's "Write less code!" stuff, doesn't have the way for do it without code duplicating.
Thanks!
You cannot use the new action as it is, though you can put your form in one partial, use across new and your action to generate form in modal.
On Page load you can use _form partial.
You can use ajax to generate the form for the model if you want on fly, this can be use for edit as well as new.
Step1 :link_to "your action path", remote: true, id: "abc"
Step2: your action path should return html of the form using render to string
Step3: now using jquery ajax success of $("#abc") replace your model inner content with the form.
And use the create action for both ajax and postback.
Code is DRY.
Let me know if you need the code.
Thanks

Why after render an partial,#users_shown is nil?

In controller, I have #users_shown. In views, I render a partial _attendants.html.haml with #users_shown.
It's okay but there is a button on this page called attend_again, while you click this button, it will render the partial via AJAX with partial _attendants.html.haml.
The question is in the partial _attendants.html.haml, #users_shown is nil. I don't know why.
file _attendants.html.haml like this
- unless #users_shown.blank?
-#users_shown.each do |user|
user.name,user.id
You need to set #users_shown in your controller action that is rendering the ajax _attendants partial. It's a completely separate request, and needs all relevant data set appropriately.
Try add a local to the partial rendering like:
<%= render :partial => "xxxx/_page_attendants", :locals => { :users_shown => #users_shown } %>

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