Rails Instance Variable Accessibility Inside Layout - ruby-on-rails

This may be a silly question, but I'm curious to know how it works. Here is the scenario:
Controller
def some_method
#abc = true
render :template => "show", :layout => "lightbox"
end
Now, when I try to access the instance variable #abc inside layout, it comes out to be nil. But, for following scenario:
Controller
def some_method
render :template => "show", :layout => "lightbox"
end
View (show.html.haml)
- #abc = true
The variable is accessible inside layout.
My question is:
Why is it different that I define an instance variable inside view, it's accessible in layout, but if the same variable is defined in controller instead of view, it's not accessible and come as nil?

In the first case: When you use render in the controller action, it does not inherit the controller action scope automatically. You would have to pass the variable to the render call. Something like:
render :template => "show", :layout => "lightbox", :locals => {abc: #abc}
In the view template you would be able to access the variable abc (without the #), containing the controller #abc variable contents
In the second case: when processing the template "show", rails is creating the #abc variable inside the view scope. So you can access it.
The answers provided in this other question can help you understand what is happening. And the Rails API docs are also a good reference for you

Related

How to pass variable to render in controller method in Rails

I am trying to pass a variable to render like this:
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
render 'index', type: 'Monitor'
end
Here i want to use 'type' variable inside index view which looks like that:
<%= render 'some_partial', periphery_type: type %>
which also render something. But i want to use that 'type' variable
There are two ways to pass variables between the controller and views:
Instance variables
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
#type = 'Monitor'
render 'index'
end
Rails will export any of the instance variables belonging to the controller to the view context. So you can call #type in the view or any partial.
Locals
def monitor
#peripheries = Periphery.where('periphery_type_name=?','monitor')
render 'index', locals: { type: 'Monitor' }
end
Note that you need to pass a hash to the locals option. You also need to pass the local variable to partial views:
<%= render 'some_partial', locals: { periphery_type: type } %>
Using locals is often a good idea since it encourages decoupling and can make your partials more reusable.
You can use redirect_to some_path(params: params)
In the monitor method, you can pass the type variable to the index view e.g.
def monitor
#type = 'monitor'
#peripheries = Periphery.where('periphery_type_name = ?', #type)
render 'index'
end
and in your view
<%= render 'some_partial', locals: {periphery_type: #type}
(Note this is not a good way to set up the type variable, I would need a better understanding of the class to suggest how to set that variable.)

How to render alternate show view in Rails 3?

In my Rails 3 app, my 'show' view renders a submitted form. I'd like to create an 'info' view that displays different data from the same submitted form. It's basically an alternate show view.
I put this into my controller, but it doesn't work:
def show
#form = Form.find(params[:id])
end
def info
#form = Form.find(params[:id])
render :layout => 'info'
end
All it does is display the 'show' view. How do I correct this?
The problem must lie elsewhere, because those two actions look fine. In this example, your show action should use your show view, and your info action should use your info view (albeit with a layout also called "info" - you might want to consider renaming that so you don't get confused between your layout and your view).
Are you sure your routes are set up properly? Do you have an 'info' route set up for your Form model? i.e.
routes.rb:
resources :forms do
get :info
end
And are you navigating to the right URL? (in this case, http://yourhost/forms/123/info)?
You can call
def info
#form = Form.find(params[:id])
render :action => 'show'
end
and it will use the #form instance variable defined in the info method, make sure you have the proper routes setup

Rails 3 Custom Method Location

I am currently trying to add some parsing methods to a controller method in a Rails 3 application.
I have a controller action as follows:
def control
#device = Device.find(params[:id])
<do things>
parse_return(#returned_data)
end
and I added a custom method to the controller as below (this method would not have any routes and would only be accessible to controller actions):
def parse_return
<parse data>
end
but this does not appear to allow the parse_return method to be used. Is there somewhere else in the Rails app that I can put re-usable methods?
Thanks!
At a first glance it seems that you fail to render a response. Is it true that control action doesn't have an associated view?
In this case you have to manually call render in your action. For example, to render JSON response you can do this:
def control
# ...
render :json => parse_return(#returned_data),
:content_type => 'application/json',
:layout => false
end
You should include what the errors are.
What happens if you try this?
def parse_return(returned_data)
<parse data>
end
Perhaps the method is not expecting an parameter to be passed along with it.

Rails rendering file with locals using instance variable

I've just updated to Rails 2.3.11. In an earlier version I could write the following
render :file=>'console/users/show.html.erb', :locals => {:#user => #users.first}
which no longer works, instead I need to write
render :file=>'console/users/show.html.erb', :locals => {:user => #users.first}
which means to access the user in the file I would use 'user' but in the file I would like to use the instance variable #user as this same show file is called from the controller and passes #user
Any tips?
Thanks
Set #user before calling render:
#user = #users.first
render :file=>'console/users/show.html.erb'
The :locals option should only be used if you are passing local variables through.

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

Resources