Render cached action of another controller inside erb template - ruby-on-rails

I want to render action inside my erb template.
<div>
<%= render :controller => :tags, :action => :tag_cloud %>
</div>
This block throws exception: undefined method `formats' for nil:NilClass
Also I want to tag_cloud action to be rendered from cache. Is that possible?
Regards,
Alexey Zakhaov

Just remind that render :action does not run the tags controller, it just renders the tag_cloud erb with the variables you have defined in your current controller.
So you have to define in your controller all the instance variables you need in your template, including the one on which the formats method is called.

Related

View inside other view

In a Rails application I have a view index.html.erb and a controller posts_controller.rb.
In the controller I have defined a variable:
def index
#posts = TableName.find...
and in the view I have:
<% #posts.each do |post| %>
If I access it via localhost/posts/index it works fine. But what I really want is to show this view inside other views so I'm using <%= render :template => 'posts/index' %> but I get this error message: "NoMethodError - You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.each"
How can I do this? Thanks
NoMethodError is triggered when you try to call methods on undefined object. In other word, you render posts/index in other views, but #posts instance variable is not defined in the other view. render template does not route the controller.

Rendering Rails partial view (with issues reading the Rails API)

I have a jQuery post submitting a form to a controller create action, which works great. If the save was successful I would like the create action to return a different form so the success callback will insert this form. Is this possible?
Here's my code:
def create
#event = Event.new(params[:event])
if #event.save
# This is where I would like to render a different controller action's view.
render :controller => "shows", :action => "new", :layout => false
else
render action: "new"
end
end
For some reason it will not render the "shows/new" template. It keeps rendering the current controller's new template without the layout. What am I missing here?
As an aside, I had a look at api.rubyonrails.org and tried to look up the render method. I found it listed as render(context,options), but can't for the life of me find out what the valid options are. This seems to be a common pattern for a lot of methods. How do I find out? It will certainly help me figure out what my options are, and perhaps give various things a try.
Thanks,
Dany.
ADDED: I have now used render "shows/new", :layout => false in my controller action, which is working. In my new.html.erb for Shows I have declared <%= render "/shows/form" %>. Unfortunately I am now getting 500 error. I found this in development.log:
ActionView::Template::Error (undefined method `model_name' for NilClass:Class):
1: <%= form_for(#show) do |f| %>
2: <% if #show.errors.any? %>
3: <div id="error_explanation">
4: <h2><%= pluralize(#show.errors.count, "error") %> prohibited this show from being saved:</h2>
app/views/shows/_form.html.erb:1:in `_app_views_shows__form_html_erb___1397093944823648986_2158339140'
app/views/shows/new.html.erb:3:in `_app_views_shows_new_html_erb__1152608637968596369_2158584080'
app/controllers/events_controller.rb:61:in `create'
I'm not entirely sure what's causing this...
Seems you missed: 2.2.3 Rendering an Action’s Template from Another Controller
Try:
render "shows/new", :layout => false

Rails3 rendering action from another controller

i want to render an action from another controller, but i get the error:
undefined method `formats' for nil:NilClass
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").html("<%= escape_javascript(render(:controller => 'live_validation', :action => 'validate_client_company')) %>");
});
</script>
This is the Controller:
class LiveValidationsController < ApplicationController
def validate_client_company
if params[:first_name].length > 0
#client = Client.find_by_company(params[:company])
if #client.nil?
#message = "<img src='/images/accepted_48.png' alt='Valid Username'/>"
else
#message = "<img src='/images/cancel_48.png' alt='Invalid Username' /> Name taken"
end
else
#message = ""
end
render :partial => "message"
end
end
The partial _message is just
<%= #message %>
You seem to be mixing up stuff.
You have html inside your controller-method? That should be in your view. For each controller-method, normally a view with the same name is rendered, except if you explicitly call render from within your controller-method.
You do not write html in your controller. You write html in the view, and sometimes you have helpers to make your views more readable.
Secondly, in your first piece of code, which is some view-code, i hope. The view is prepared at server-side and then sent to the client. You can render another view, a partial, from a view. But this does not load data live.
How i would fix this. Inside your views where you want to dynamically render the validation:
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("<%= url_for :controller => 'live_validations', :action => 'validate_client_company' %>");
});
</script>
Then inside your controller you write:
class LiveValidationsController < ApplicationController
def validate_client_company
if params[:first_name].length > 0
#client = Client.find_by_company(params[:company])
#error = #client.nil? ? :valid_username : :invalid_username
else
#error = nil
end
render :partial => "message", :layout => false
end
end
Inside your app/helper/live_validations_helper.rb you add a method
def get_validation_message(error)
if error == :invalid_username
image_tag('/images/cancel_48.png', :alt => 'Invalid Username') + "Name taken"
elsif error == :valid_username
image_tag('/images/accepted_48.png', :alt => 'Valid Username')
end
end
and inside your message view you write something like:
<%= get_validation_message(#error) %>
render :action => does not run the associated controller method.
It simply renders the template that Rails would, by default, have associated with the action. That is to say, if the action validate_client_company simply called render without passing any arguments, Rails would look for a template in a folder with the same name as the controller and with a name with the same name as the action. Calling render :action => simply looks for that same template and renders it.
Best guess is that Rails cannot find a template named validate_client_company. I expect that none exists, because the action validate_client_company renders a partial named message instead of rendering a template with the default name for that action.
In the action which renders the script, you need to set up the instance variables and then in the template for that action you need to use the following:
render :partial => 'live_validations/message'
It certainly makes sense to have mini MVC stacks within the larger MVC stack, so that you can run sub-actions within running larger actions. For this scenario, you may wish to look at Cells. However, you cannot do this with Rails by itself.
You probably want something like this:
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("<%= url_for :controller => 'live_validation', :action => 'validate_client_company' %>");
});
</script>
But the rest of your code is kinda of messed up... Rendering a partial from inside a controller?
Got it to work!
<script>
$("#validate_company").live("keyup", function() {
$("#company_info").load("/live_validations/validate_client_company",{company:$('#validate_company').val()});
});
</script>

Is it possible to use partials with the layout option inside of a controller?

When try I following code in a controller, the view renders without using the layout
def xyz
render :partial => 'platinum_home', :layout => 'platinum_layout'
end
But If I do the following inside the partial
<% render(:layout => "platinum_layout") do %>
blah blah blah
<% end %>
It works just fine, is the first example not possible using rails?
In your controller at the top add the following:
class SomeController < ApplicationController
layout "platinum_layout", :only => :xyz
Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page without reloading. Rendering of partials from the controller makes it possible to use the same partial template in both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the controller action responding to Ajax calls). By default, the current layout is not used.
So to use current layout for your just used.
def xyz
render :partial => 'platinum_home', :layout => true
end

Ruby on Rails form_remote_tag missing template

I'm using form_remote_tag(:url => {:controller => "home", :action => "search"}, :update => "mydiv"). When I click submit on the form "mydiv" is populated with the error "Template is missing. Missing template home/search.erb in view path app/views". I've tried multiple render options in def search, but they all result in the same error.
It looks like the search method is trying to use it's default render even though I'm specifying what I want.
I've tried:
render 'index'
render :text => 'Return this from my method!'
Is my url incorrect? Is it not submitting back to my home controller's search method?
Try
render :action => 'index'
this will use "index.rhtml" or "index.html.erb".
I will try to explain why it said search.erb is not found, lets take create action for a some model, if there is some error in my create action they it will throw missing template create.html.erb file, since you have some error in your create action rails will try to render the create.html.erb in the page. Hope I explained it clearly.
In an ajax action you can't use redirect_to or render options directly.
try using this in your search action
render :update do |page|
page.replace_html "ur_div_id","partial"
end
The form_remote_tag needs prototype to function. Make sure you are including the :defaults for your javascript libraries namely prototype.
<%= javascript_include_tag :defaults %>

Resources